diff --git a/Directory.Build.props b/Directory.Build.props index dea0a6c6f7..d888f2a60a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,16 +2,16 @@ - 5.0.0 + 5.0.* - 16.6.1 + 16.8.3 4.2.2 - 3.0.2 + 4.0.1 2.4.1 @@ -20,7 +20,7 @@ 2.4.1 - 2.4.2 + 2.4.3 2.2.14 diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index e029499b06..0d465e6966 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -32,6 +32,7 @@ "MyProfile": "My profile", "EmailNotValid": "Please enter a valid email address.", "JoinOurMarketingNewsletter": "Join our marketing newsletter", - "WouldLikeToReceiveMarketingMaterials": "I would like to receive marketing materials like product deals & special offers." + "WouldLikeToReceiveMarketingMaterials": "I would like to receive marketing materials like product deals & special offers.", + "StartUsingYourLicenseNow": "Start using your license now!" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json index 492229d6bb..e1dd405851 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json @@ -184,6 +184,14 @@ "ABPCLIExamplesInfo": "new command creates a layered MVC application with Entity Framework Core as the database provider. However, it has additional options. Examples:", "SeeCliDocumentForMoreInformation": "See the ABP CLI document for more options or select the \"Direct Download\" tab above.", "Optional": "Optional", - "LocalFrameworkRef": "Keep local project reference for the framework packages." + "LocalFrameworkRef": "Keep local project reference for the framework packages.", + "BlobStoring": "BLOB Storing", + "BlobStoringExplanation": "BLOB Storing system provides an abstraction to work with BLOBs. ABP provides some pre-built storage provider integrations (Azure, AWS, File System, Database, etc.) that you can easily use in your applications.", + "TextTemplating": "Text Templating", + "TextTemplatingExplanation": "Text templating is used to dynamically render contents based on a template and a model (a data object). For example, you can use it to create dynamic email contents with a pre-built template.", + "MultipleUIOptions": "Multiple UI Options", + "MultipleDBOptions": "Multiple Database Providers", + "MultipleUIOptionsExplanation": "The core framework is designed as UI independent and can work with any type of UI system, while there are multiple pre-built and integrated options are provided out of the box.", + "MultipleDBOptionsExplanation": "The framework can work with any data source, while the following providers are officially developed and supported;" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json index 4dcb0cad51..6e9d9bf0da 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json @@ -184,6 +184,13 @@ "ABPCLIExamplesInfo": "new命令创建一个 分层的MVC应用程序 使用 Entity Framework Core 做为数据库提供程序. 它还有其他选项. 示例:", "SeeCliDocumentForMoreInformation": "参阅 ABP CLI 文档 获得更多选项或选择上方的 \"直接下载\" 标签.", "Optional": "可选的", - "LocalFrameworkRef": "保留框架包的本地项目引用." + "LocalFrameworkRef": "保留框架包的本地项目引用.", + "BlobStoring": "BLOB存储", + "BlobStoringExplanation": "BLOB存储系统提供了BLOB的抽象. ABP提供了一些预构建的存储提供程序集成(Azure,AWS,文件系统,数据库等),你可以轻松的在你的应用程序中使用它们.", + "TextTemplating": "文本模板", + "TextTemplatingExplanation": "文本模板是基于模板和模型(数据对象)使用动态渲染内容. 例如你可以使用预构建的模板来创建动态的电子邮件内容.", + "MultipleUIOptions": "多个UI选项", + "MultipleDBOptions": "多个数据库提供程序", + "MultipleUIOptionsExplanation": "核心框架设计为独立与UI,可以和任何类型的UI系统一起使用. 同时提供了多个开箱即用的预构建集成选项." } } \ No newline at end of file diff --git a/common.props b/common.props index 1528abbcc6..1e69d68aa2 100644 --- a/common.props +++ b/common.props @@ -9,8 +9,15 @@ git https://github.com/abpframework/abp/ true + + + true + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb - + + all + runtime; build; native; contentfiles; analyzers + \ No newline at end of file diff --git a/docs/en/Authorization.md b/docs/en/Authorization.md index bceca3548f..fbb71bb3d4 100644 --- a/docs/en/Authorization.md +++ b/docs/en/Authorization.md @@ -280,21 +280,11 @@ public async Task CreateAsync(CreateAuthorDto input) ## Check a Permission in JavaScript -You may need to check a policy/permission on the client side. +See the following documents to learn how to re-use the authorization system on the client side: -### MVC UI - -For ASP.NET Core MVC / Razor Pages applications, you can use the `abp.auth` API. - -**Example: Check if a given permission has been granted for the current user** - -```js -abp.auth.isGranted('MyPermissionName'); -``` - -### Angular UI - -See the [permission management document](UI/Angular/Permission-Management.md) for the Angular UI. +* [ASP.NET Core MVC / Razor Pages UI: Authorization](UI/AspNetCore/JavaScript-API/Auth.md) +* [Angular UI Authorization](UI/Angular/Permission-Management.md) +* [Blazor UI Authorization](UI/Blazor/Authorization.md) ## Permission Management diff --git a/docs/en/CLI.md b/docs/en/CLI.md index d51dd91b5d..c5eb38bbbe 100644 --- a/docs/en/CLI.md +++ b/docs/en/CLI.md @@ -129,6 +129,7 @@ abp update [options] * `--solution-path` or `-sp`: Specify the solution path. Use the current directory by default * `--solution-name` or `-sn`: Specify the solution name. Search `*.sln` files in the directory by default. * `--check-all`: Check the new version of each package separately. Default is `false`. +* `--version` or `-v`: Specifies the version to use for update. If not specified, latest version is used. ### add-package diff --git a/docs/en/Community-Articles/2020-09-16-How-to-Setup-Azure-Active-Directory-and-Integrate-Abp-Angular-Application/POST.md b/docs/en/Community-Articles/2020-09-16-How-to-Setup-Azure-Active-Directory-and-Integrate-Abp-Angular-Application/POST.md index b286bb509d..c7f4f40917 100644 --- a/docs/en/Community-Articles/2020-09-16-How-to-Setup-Azure-Active-Directory-and-Integrate-Abp-Angular-Application/POST.md +++ b/docs/en/Community-Articles/2020-09-16-How-to-Setup-Azure-Active-Directory-and-Integrate-Abp-Angular-Application/POST.md @@ -1,22 +1,22 @@ -# How to Setup Azure Active Directory and Integrate Abp Angular Application +# How to Setup Azure Active Directory and Integrate ABP Angular Application -This guide demonstrates how to register an application to Azure Active Directory and integrate AzureAD to an ABP angular application that enables users to sign in using OAuth 2.0 with credentials from **Azure Active Directory**. +This guide demonstrates how to register an application to Azure Active Directory and integrate AzureAD to an ABP Angular application that enables users to sign in using OAuth 2.0 with credentials from **Azure Active Directory**. ## Authentication Flow -Abp angular applications use **Authentication Code with PKCE** (specs [here](https://tools.ietf.org/html/rfc7636)) which is the most suitable flow for spa applications by the time this article is written since implicit flow is deprecated. +ABP Angular application uses **Authentication Code with PKCE** (specs [here](https://tools.ietf.org/html/rfc7636)) which is the most suitable flow for SPA applications by the time this article is written since implicit flow is deprecated. The most common question is; -> Where to put OpenId connection code in angular project? +> Where to put OpenId connection code in the Angular project? -The answer is, **you don't**. Abp angular application is integrated with backend code (HttpApi.Host project) where it loads the configurations, **permissions** etc. For none-tiered angular applications, **HttpApi.Host** project also has IdentityServer4 embedded; also serving as **Authorization Server**. Angular application authentication flow is shown below. +The answer is, **you don't**. ABP Angular application is integrated with the backend (HttpApi.Host project) where it loads the configurations, **permissions** etc. For none-tiered angular applications, **HttpApi.Host** project also has IdentityServer4 embedded; also serving as **Authorization Server**. Angular application authentication flow is shown below. auth-diagram > What if I want Azure AD as my authorization server and not IdentityServer? -This means your application will be using AzureAD user store for authentication. By registering both angular app and HttpApi to AzureAD, authentication might work but **authorization won't**. Users need to be registered to Abp identity system for auditing, permissions etc. So the flow should be 3rd party registration. +This means your application will be using AzureAD user store for authentication. By registering both Angular app and HttpApi to AzureAD, authentication might work but **authorization won't**. Users need to be registered to ABP identity system for auditing, permissions etc. So the flow should be 3rd party registration. ## Setting up OpenId Connection diff --git a/docs/en/Community-Articles/2020-12-04-Event-Organizer/Post.md b/docs/en/Community-Articles/2020-12-04-Event-Organizer/Post.md new file mode 100644 index 0000000000..b36d83d0ba --- /dev/null +++ b/docs/en/Community-Articles/2020-12-04-Event-Organizer/Post.md @@ -0,0 +1,936 @@ +# Creating an Event Organizer Application with the ABP Framework & Blazor UI. + +## Introduction + +In this article, we will create an example application that is a simple **meeting/event organizer**: People create events and other people registers to the event. + +The application has been developed with **Blazor** as the UI framework and **MongoDB** as the database provider. + +> This tutorial is based on my notes that I'd created to implement this application in a workshop. It shows the necessary steps to build the application rather than detailed explanations. + +### Source Code + +Source code of the completed application is [available on GitHub](https://github.com/abpframework/abp-samples/tree/master/EventOrganizer). + +### Screenshots + +Here, the pages of the final application. + +**Home Page - Event List** + +![event-list-ui](images/event-list-ui.png) + +**Creating a new Event** + +![event-create-ui](images/event-create-ui.png) + +**Event Detail Page** + +![event-detail-ui](images/event-detail-ui.png) + +## Requirements + +The following tools are needed to be able to run the solution. + +* .NET 5.0 SDK +* Visual Studio 2019 16.8.0+ or another compatible IDE +* MongoDB Server (with MongoDB Compass) + +## Development + +### Creating a new Application + +* Use the following ABP CLI command: + +````bash +abp new EventOrganizer -u blazor -d mongodb +```` + +### Open & Run the Application + +* Open the solution in Visual Studio (or your favorite IDE). +* Run the `EventOrganizer.DbMigrator` application to seed the initial data. +* Run the `EventOrganizer.HttpApi.Host` application that starts the server side. +* Run the `EventOrganizer.Blazor` application to start the UI. + +### Apply the Custom Styles + +* Add styles to `wwwroot/main.css`: + +````css +body.abp-application-layout { + background-color: #222 !important; + font-size: 18px; +} +nav#main-navbar.bg-dark { + background-color: #222 !important; + box-shadow: none !important; +} +.event-pic { + width: 100%; + border-radius: 12px; + box-shadow: 5px 5px 0px 0px rgba(0,0,0,.5); + margin-bottom: 10px; +} +.event-link:hover, .event-link:hover *{ + text-decoration: none; +} +.event-link:hover .event-pic { + box-shadow: 5px 5px 0px 0px #ffd800; +} +.event-form { + background-color: #333 !important; + box-shadow: 5px 5px 0px 0px rgba(0,0,0,.5); + border-radius: 12px; +} +.table { + background: #fff; + border-radius: 12px; + box-shadow: 5px 5px 0px 0px rgba(0,0,0,.5); +} +.table th{ + border: 0 !important; +} +.modal { + color: #333; +} +.page-item:first-child .page-link { + margin-left: 0; + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} +.page-item:last-child .page-link { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} +.btn { + border-radius: 8px; +} +.att-list { + list-style: none; + padding: 0; +} +.att-list li { + padding: 4px 0 0 0; +} +```` + +* `wwwroot/index.html`: Remove `bg-light` class from the `body` tag and add `bg-dark text-light`. + +### Domain Layer + +* Add the following `Event` aggregate (with `EventAttendee`) to the solution: + +**Event** + +````csharp +using System; +using System.Collections.Generic; +using Volo.Abp.Domain.Entities.Auditing; + +namespace EventOrganizer.Events +{ + public class Event : FullAuditedAggregateRoot + { + public string Title { get; set; } + + public string Description { get; set; } + + public bool IsFree { get; set; } + + public DateTime StartTime { get; set; } + + public ICollection Attendees { get; set; } + + public Event() + { + Attendees = new List(); + } + } +} +```` + +**EventAttendee** + +```csharp +using System; +using Volo.Abp.Auditing; + +namespace EventOrganizer.Events +{ + public class EventAttendee : IHasCreationTime + { + public Guid UserId { get; set; } + + public DateTime CreationTime { get; set; } + } +} +``` + +### MongoDB Mapping + +* Add the following property to the `EventOrganizerMongoDbContext`: + +````csharp +public IMongoCollection Events => Collection(); +```` + +### Clean Index.razor & Add the Header & "Create Event" button + +* Clean the `Index.razor` file. +* Replace the content with the following code: + +````html +@page "/" +@inherits EventOrganizerComponentBase + + +

Upcoming Events

+
+ + @if (CurrentUser.IsAuthenticated) + { + + @L["CreateEvent"] + + } + +
+```` + +* Open `Localization/EventOrganizer/en.json` in the `EventOrganizer.Domain.Shared` project and add the following entry: + +````json +"CreateEvent": "Create a new event!" +```` + +The Result (run the `EventOrganizer.Blazor` application to see): + +![index-title](images/index-title.png) + +### Event Creation + +* Create the Initial `IEventAppService` with the `CreateAsync` method: + +````csharp +using System; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace EventOrganizer.Events +{ + public interface IEventAppService : IApplicationService + { + Task CreateAsync(EventCreationDto input); + } +} +```` + +* Add `EventCreationDto` class: + +````csharp +using System; +using System.ComponentModel.DataAnnotations; + +namespace EventOrganizer.Events +{ + public class EventCreationDto + { + [Required] + [StringLength(100)] + public string Title { get; set; } + + [Required] + [StringLength(2000)] + public string Description { get; set; } + + public bool IsFree { get; set; } + + public DateTime StartTime { get; set; } + } +} +```` + +* Implement the `EventAppService`: + +````csharp +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Volo.Abp.Domain.Repositories; + +namespace EventOrganizer.Events +{ + public class EventAppService : EventOrganizerAppService, IEventAppService + { + private readonly IRepository _eventRepository; + + public EventAppService(IRepository eventRepository) + { + _eventRepository = eventRepository; + } + + [Authorize] + public async Task CreateAsync(EventCreationDto input) + { + var eventEntity = ObjectMapper.Map(input); + await _eventRepository.InsertAsync(eventEntity); + return eventEntity.Id; + } + } +} +```` + +* Add AutoMapper mapping to the `EventOrganizerApplicationAutoMapperProfile` class: + +````csharp +using AutoMapper; +using EventOrganizer.Events; + +namespace EventOrganizer +{ + public class EventOrganizerApplicationAutoMapperProfile : Profile + { + public EventOrganizerApplicationAutoMapperProfile() + { + CreateMap(); + } + } +} +```` + +This will automatically create the HTTP (REST) API for the application service (run the `EventOrganizer.HttpApi.Host` application to see it on the Swagger UI): + +![swagger-event-create](images/swagger-event-create.png) + +* Create the `CreateEvent.razor` file: + +````csharp +@page "/create-event" +@inherits EventOrganizerComponentBase +Create Event + + +
+ + + @L["Title"] + + + + @L["Description"] + + + + @L["Free"] + + + @L["StartTime"] + + + + +
+
+
+```` + +* Create a partial `CreateEvent` class in the same folder, with the `CreateEvent.razor.cs` as the file name: + +````csharp +using System.Threading.Tasks; +using EventOrganizer.Events; +using Microsoft.AspNetCore.Components; + +namespace EventOrganizer.Blazor.Pages +{ + public partial class CreateEvent + { + private EventCreationDto Event { get; set; } = new EventCreationDto(); + + private readonly IEventAppService _eventAppService; + private readonly NavigationManager _navigationManager; + + public CreateEvent( + IEventAppService eventAppService, + NavigationManager navigationManager) + { + _eventAppService = eventAppService; + _navigationManager = navigationManager; + } + + private async Task Create() + { + var eventId = await _eventAppService.CreateAsync(Event); + _navigationManager.NavigateTo("/events/" + eventId); + } + } +} +```` + +The final UI is (run the `EventOrganizer.Blazor` application and click to the "Create Event" button): + +![event-create-ui](images/event-create-ui.png) + +### Upcoming Events (Home Page) + +* Open the `IEventAppService` and add a `GetUpcomingAsync` method to get the list of upcoming events: + +````csharp +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace EventOrganizer.Events +{ + public interface IEventAppService : IApplicationService + { + Task CreateAsync(EventCreationDto input); + + Task> GetUpcomingAsync(); + } +} +```` + +* Add a `EventDto` class: + +````csharp +using System; +using Volo.Abp.Application.Dtos; + +namespace EventOrganizer.Events +{ + public class EventDto : EntityDto + { + public string Title { get; set; } + + public string Description { get; set; } + + public bool IsFree { get; set; } + + public DateTime StartTime { get; set; } + + public int AttendeesCount { get; set; } + } +} +```` + +* Implement the `GetUpcomingAsync` in the `EventAppService` class: + +````csharp +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Volo.Abp.Domain.Repositories; + +namespace EventOrganizer.Events +{ + public class EventAppService : EventOrganizerAppService, IEventAppService + { + private readonly IRepository _eventRepository; + + public EventAppService(IRepository eventRepository) + { + _eventRepository = eventRepository; + } + + [Authorize] + public async Task CreateAsync(EventCreationDto input) + { + var eventEntity = ObjectMapper.Map(input); + await _eventRepository.InsertAsync(eventEntity); + return eventEntity.Id; + } + + public async Task> GetUpcomingAsync() + { + var events = await AsyncExecuter.ToListAsync( + _eventRepository + .Where(x => x.StartTime > Clock.Now) + .OrderBy(x => x.StartTime) + ); + + return ObjectMapper.Map, List>(events); + } + } +} +```` + +* Add the following line into the `EventOrganizerApplicationAutoMapperProfile` constructor: + +````csharp +CreateMap(); +```` + +Run the `EventOrganizer.HttpApi.Host` application to see the new `upcoming` endpoint on the Swagger UI: + +![swagger-event-upcoming](images/swagger-event-upcoming.png) + +* Change the `Pages/Index.razor.cs` content in the `EventOrganizer.Blazor` project as shown below: + +```csharp +using System.Collections.Generic; +using System.Threading.Tasks; +using EventOrganizer.Events; + +namespace EventOrganizer.Blazor.Pages +{ + public partial class Index + { + private List UpcomingEvents { get; set; } = new List(); + + private readonly IEventAppService _eventAppService; + + public Index(IEventAppService eventAppService) + { + _eventAppService = eventAppService; + } + + protected override async Task OnInitializedAsync() + { + UpcomingEvents = await _eventAppService.GetUpcomingAsync(); + } + } +} +``` + +* Change the `Pages/Index.razor` content in the `EventOrganizer.Blazor` project as shown below: + +````html +@page "/" +@inherits EventOrganizerComponentBase + + +

Upcoming Events

+
+ + @if (CurrentUser.IsAuthenticated) + { + + @L["CreateEvent"] + + } + +
+ + @foreach (var upcomingEvent in UpcomingEvents) + { + + +
+ @if (upcomingEvent.IsFree) + { + FREE + } + + + @upcomingEvent.AttendeesCount + +
+ +
+ @upcomingEvent.StartTime.ToLongDateString() +

@upcomingEvent.Title

+

@upcomingEvent.Description.TruncateWithPostfix(150)

+
+
+
+ } +
+```` + +The new home page is shown below: + +![event-list-ui](images/event-list-ui.png) + +### Event Detail Page + +* Add `GetAsync`, `RegisterAsync`, `UnregisterAsync` and `DeleteAsync` methods to the `IEventAppService`: + +````csharp +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace EventOrganizer.Events +{ + public interface IEventAppService : IApplicationService + { + Task CreateAsync(EventCreationDto input); + + Task> GetUpcomingAsync(); + + Task GetAsync(Guid id); + + Task RegisterAsync(Guid id); + + Task UnregisterAsync(Guid id); + + Task DeleteAsync(Guid id); + } +} +```` + +* Add `EventDetailDto` class: + +````csharp +using System; +using System.Collections.Generic; +using Volo.Abp.Application.Dtos; + +namespace EventOrganizer.Events +{ + public class EventDetailDto : CreationAuditedEntityDto + { + public string Title { get; set; } + + public string Description { get; set; } + + public bool IsFree { get; set; } + + public DateTime StartTime { get; set; } + + public List Attendees { get; set; } + } +} +```` + +* Add `EventAttendeeDto` class: + +````csharp +using System; + +namespace EventOrganizer.Events +{ + public class EventAttendeeDto + { + public Guid UserId { get; set; } + + public string UserName { get; set; } + + public DateTime CreationTime { get; set; } + } +} +```` + +* Implement the new methods in the `EventAppService`: + +````csharp +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using EventOrganizer.Users; +using Microsoft.AspNetCore.Authorization; +using Volo.Abp; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Users; + +namespace EventOrganizer.Events +{ + public class EventAppService : EventOrganizerAppService, IEventAppService + { + private readonly IRepository _eventRepository; + private readonly IRepository _userRepository; + + public EventAppService(IRepository eventRepository, IRepository userRepository) + { + _eventRepository = eventRepository; + _userRepository = userRepository; + } + + [Authorize] + public async Task CreateAsync(EventCreationDto input) + { + var eventEntity = ObjectMapper.Map(input); + await _eventRepository.InsertAsync(eventEntity); + return eventEntity.Id; + } + + public async Task> GetUpcomingAsync() + { + var events = await AsyncExecuter.ToListAsync( + _eventRepository + .Where(x => x.StartTime > Clock.Now) + .OrderBy(x => x.StartTime) + ); + + return ObjectMapper.Map, List>(events); + } + + public async Task GetAsync(Guid id) + { + var @event = await _eventRepository.GetAsync(id); + var attendeeIds = @event.Attendees.Select(a => a.UserId).ToList(); + var attendees = (await AsyncExecuter.ToListAsync(_userRepository.Where(u => attendeeIds.Contains(u.Id)))) + .ToDictionary(x => x.Id); + + var result = ObjectMapper.Map(@event); + + foreach (var attendeeDto in result.Attendees) + { + attendeeDto.UserName = attendees[attendeeDto.UserId].UserName; + } + + return result; + } + + [Authorize] + public async Task RegisterAsync(Guid id) + { + var @event = await _eventRepository.GetAsync(id); + if (@event.Attendees.Any(a => a.UserId == CurrentUser.Id)) + { + return; + } + + @event.Attendees.Add(new EventAttendee {UserId = CurrentUser.GetId(), CreationTime = Clock.Now}); + await _eventRepository.UpdateAsync(@event); + } + + [Authorize] + public async Task UnregisterAsync(Guid id) + { + var @event = await _eventRepository.GetAsync(id); + var removedItems = @event.Attendees.RemoveAll(x => x.UserId == CurrentUser.Id); + if (removedItems.Any()) + { + await _eventRepository.UpdateAsync(@event); + } + } + + [Authorize] + public async Task DeleteAsync(Guid id) + { + var @event = await _eventRepository.GetAsync(id); + + if (CurrentUser.Id != @event.CreatorId) + { + throw new UserFriendlyException("You don't have the necessary permission to delete this event!"); + } + + await _eventRepository.DeleteAsync(id); + } + } +} +```` + +* Add the following mappings into the `EventOrganizerApplicationAutoMapperProfile`: + +````csharp +CreateMap(); +CreateMap(); +```` + +Run the `EventOrganizer.HttpApi.Host` application to see the complete Event HTTP API in the Swagger UI: + +![swagger-event-all](images/swagger-event-all.png) + +* Create `EventDetail.razor` component with the following content: + +````html +@page "/events/{id}" +@inherits EventOrganizerComponentBase +@if (Event != null) +{ + + +

@Event.Title

+
+ + Back + @if (CurrentUser.IsAuthenticated && CurrentUser.Id == Event.CreatorId) + { + + } + +
+ + +
+
+ @if (Event.IsFree) + { + FREE + } + + + @Event.Attendees.Count + +
+ + Start time: @Event.StartTime.ToLongDateString() +

@Event.Description

+
+
+ +
+ @if (CurrentUser.IsAuthenticated) + { +
+ @if (!IsRegistered) + { + + } + else + { +

You are registered in this event

+ + } +
+ } + else + { + + Login to attend! + + } +
+
+ Attendees (@Event.Attendees.Count) +
    + @foreach (var attendee in Event.Attendees) + { +
  • @attendee.UserName
  • + } +
+
+
+
+} +```` + +* Create `EventDetail.razor.cs` file with the following content: + +````csharp +using System; +using System.Linq; +using System.Threading.Tasks; +using EventOrganizer.Events; +using Microsoft.AspNetCore.Components; + +namespace EventOrganizer.Blazor.Pages +{ + public partial class EventDetail + { + [Parameter] + public string Id { get; set; } + + private EventDetailDto Event { get; set; } + private bool IsRegistered { get; set; } + + private readonly IEventAppService _eventAppService; + private readonly NavigationManager _navigationManager; + + public EventDetail( + IEventAppService eventAppService, + NavigationManager navigationManager) + { + _eventAppService = eventAppService; + _navigationManager = navigationManager; + } + + protected override async Task OnInitializedAsync() + { + await GetEventAsync(); + } + + private async Task GetEventAsync() + { + Event = await _eventAppService.GetAsync(Guid.Parse(Id)); + if (CurrentUser.IsAuthenticated) + { + IsRegistered = Event.Attendees.Any(a => a.UserId == CurrentUser.Id); + } + } + + private async Task Register() + { + await _eventAppService.RegisterAsync(Guid.Parse(Id)); + await GetEventAsync(); + } + + private async Task UnRegister() + { + await _eventAppService.UnregisterAsync(Guid.Parse(Id)); + await GetEventAsync(); + } + + private async Task Delete() + { + if (!await Message.Confirm("This event will be deleted: " + Event.Title)) + { + return; + } + + await _eventAppService.DeleteAsync(Guid.Parse(Id)); + _navigationManager.NavigateTo("/"); + } + } +} +```` + +The resulting page is shown below: + +![event-detail-ui](images/event-detail-ui.png) + +### Integration Tests + +Create an `EventAppService_Tests` class in the `EventOrganizer.Application.Tests` project: + +````csharp +using System; +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace EventOrganizer.Events +{ + [Collection(EventOrganizerTestConsts.CollectionDefinitionName)] + public class EventAppService_Tests : EventOrganizerApplicationTestBase + { + private readonly IEventAppService _eventAppService; + + public EventAppService_Tests() + { + _eventAppService = GetRequiredService(); + } + + [Fact] + public async Task Should_Create_A_Valid_Event() + { + // Create an event + + var eventId = await _eventAppService.CreateAsync( + new EventCreationDto + { + Title = "My test event 1", + Description = "My test event description 1", + IsFree = true, + StartTime = DateTime.Now.AddDays(2) + } + ); + + eventId.ShouldNotBe(Guid.Empty); + + // Get the event + + var @event = await _eventAppService.GetAsync(eventId); + @event.Title.ShouldBe("My test event 1"); + + // Get upcoming events + + var events = await _eventAppService.GetUpcomingAsync(); + events.ShouldContain(x => x.Title == "My test event 1"); + } + } +} +```` + +## Source Code + +Source code of the completed application is [available on GitHub](https://github.com/abpframework/abp-samples/tree/master/EventOrganizer). \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/event-create-ui.png b/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/event-create-ui.png new file mode 100644 index 0000000000..c4b0c68a31 Binary files /dev/null and b/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/event-create-ui.png differ diff --git a/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/event-detail-ui.png b/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/event-detail-ui.png new file mode 100644 index 0000000000..f916a129dc Binary files /dev/null and b/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/event-detail-ui.png differ diff --git a/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/event-list-ui.png b/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/event-list-ui.png new file mode 100644 index 0000000000..4f049c2339 Binary files /dev/null and b/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/event-list-ui.png differ diff --git a/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/index-title.png b/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/index-title.png new file mode 100644 index 0000000000..c06b8f5d80 Binary files /dev/null and b/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/index-title.png differ diff --git a/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/swagger-event-all.png b/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/swagger-event-all.png new file mode 100644 index 0000000000..3b0fb24a7d Binary files /dev/null and b/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/swagger-event-all.png differ diff --git a/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/swagger-event-create.png b/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/swagger-event-create.png new file mode 100644 index 0000000000..5c7e1d0204 Binary files /dev/null and b/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/swagger-event-create.png differ diff --git a/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/swagger-event-upcoming.png b/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/swagger-event-upcoming.png new file mode 100644 index 0000000000..48d0244797 Binary files /dev/null and b/docs/en/Community-Articles/2020-12-04-Event-Organizer/images/swagger-event-upcoming.png differ diff --git a/docs/en/Exception-Handling.md b/docs/en/Exception-Handling.md index 04cc6fc695..8c84157878 100644 --- a/docs/en/Exception-Handling.md +++ b/docs/en/Exception-Handling.md @@ -1,11 +1,11 @@ # Exception Handling -ABP provides a built-in infrastructure and offers a standard model for handling exceptions in a web application. +ABP provides a built-in infrastructure and offers a standard model for handling exceptions. * Automatically **handles all exceptions** and sends a standard **formatted error message** to the client for an API/AJAX request. * Automatically hides **internal infrastructure errors** and returns a standard error message. -* Provides a configurable way to **localize** exception messages. -* Automatically maps standard exceptions to **HTTP status codes** and provides a configurable option to map these to custom exceptions. +* Provides an easy and configurable way to **localize** exception messages. +* Automatically maps standard exceptions to **HTTP status codes** and provides a configurable option to map custom exceptions. ## Automatic Exception Handling diff --git a/docs/en/Module-Entity-Extensions.md b/docs/en/Module-Entity-Extensions.md index 61a7093dc5..042c10b815 100644 --- a/docs/en/Module-Entity-Extensions.md +++ b/docs/en/Module-Entity-Extensions.md @@ -1,3 +1,393 @@ # Module Entity Extensions -See https://docs.abp.io/en/commercial/latest/guides/module-entity-extensions (it will be moved here soon). \ No newline at end of file +## Introduction + +Module entity extension system is a **high level** extension system that allows you to **define new properties** for existing entities of the depended modules. It automatically **adds properties to the entity, database, HTTP API and the user interface** in a single point. + +> The module must be developed the *Module Entity Extensions* system in mind. All the **official modules** supports this system wherever possible. + +## Quick Example + +Open the *YourProjectNameModuleExtensionConfigurator* class inside the `Domain.Shared` project of your solution and change the `ConfigureExtraProperties`method as shown below to add a `SocialSecurityNumber` property to the `IdentityUser` entity of the [Identity Module](Modules/Identity.md). + +````csharp +public static void ConfigureExtraProperties() +{ + OneTimeRunner.Run(() => + { + ObjectExtensionManager.Instance.Modules() + .ConfigureIdentity(identity => + { + identity.ConfigureUser(user => + { + user.AddOrUpdateProperty( //property type: string + "SocialSecurityNumber", //property name + property => + { + //validation rules + property.Attributes.Add(new RequiredAttribute()); + property.Attributes.Add( + new StringLengthAttribute(64) { + MinimumLength = 4 + } + ); + + //...other configurations for this property + } + ); + }); + }); + }); +} +```` + +>This method is called inside the `YourProjectNameDomainSharedModule` at the beginning of the application. `OneTimeRunner` is a utility class that guarantees to execute this code only one time per application, since multiple calls are unnecessary. + +* `ObjectExtensionManager.Instance.Modules()` is the starting point to configure a module. `ConfigureIdentity(...)` method is used to configure the entities of the Identity Module. +* `identity.ConfigureUser(...)` is used to configure the user entity of the identity module. Not all entities are designed to be extensible (since it is not needed). Use the intellisense to discover the extensible modules and entities. +* `user.AddOrUpdateProperty(...)` is used to add a new property to the user entity with the `string` type (`AddOrUpdateProperty` method can be called multiple times for the same property of the same entity. Each call can configure the options of the same property, but only one property is added to the entity with the same property name). You can call this method with different property names to add more properties. +* `SocialSecurityNumber` is the name of the new property. +* `AddOrUpdateProperty` gets a second argument (the `property =>` lambda expression) to configure additional options for the new property. + * We can add data annotation attributes like shown here, just like adding a data annotation attribute to a class property. + +#### Create & Update Forms + +Once you define a property, it appears in the create and update forms of the related entity: + +![add-new-property-to-user-form](images/add-new-property-to-user-form.png) + +`SocialSecurityNumber` field comes into the form. Next sections will explain the localization and the validation for this new property. + +### Data Table + +New properties also appear in the data table of the related page: + +![add-new-property-to-user-form](images/add-new-property-to-user-table.png) + +`SocialSecurityNumber` column comes into the table. Next sections will explain the option to hide this column from the data table. + +## Property Options + +There are some options that you can configure while defining a new property. + +### Display Name + +You probably want to set a different (human readable) display name for the property that is shown on the user interface. + +#### Don't Want to Localize? + +If your application is not localized, you can directly set the `DisplayName` for the property to a `FixedLocalizableString` object. Example: + +````csharp +property => +{ + property.DisplayName = new FixedLocalizableString("Social security no"); +} +```` + +#### Localizing the Display Name + +If you want to localize the display name, you have two options. + +##### Localize by Convention + +Instead of setting the `property.DisplayName`, you can directly open your localization file (like `en.json`) and add the following entry to the `texts` section: + +````json +"SocialSecurityNumber": "Social security no" +```` + +Define the same `SocialSecurityNumber` key (the property name you've defined before) in your localization file for each language you support. That's all! + +In some cases, the localization key may conflict with other keys in your localization files. In such cases, you can use the `DisplayName:` prefix for display names in the localization file (`DisplayName:SocialSecurityNumber` as the localization key for this example). Extension system looks for prefixed version first, then fallbacks to the non prefixed name (it then fallbacks to the property name if you haven't localized it). + +> This approach is recommended since it is simple and suitable for most scenarios. + +##### Localize using the `DisplayName` Property + +If you want to specify the localization key or the localization resource, you can still set the `DisplayName` option: + +````csharp +property => +{ + property.DisplayName = + LocalizableString.Create( + "UserSocialSecurityNumberDisplayName" + ); +} +```` + +* `MyProjectNameResource` is the localization resource and `UserSocialSecurityNumberDisplayName` is the localization key in the localization resource. + +> See [the localization document](Localization.md) if you want to learn more about the localization system. + +#### Default Value + +A default value is automatically set for the new property, which is the natural default value for the property type, like `null` for `string`, `false` for `bool` or `0` for `int`. + +There are two ways to override the default value: + +##### DefaultValue Option + +`DefaultValue` option can be set to any value: + +````csharp +property => +{ + property.DefaultValue = 42; +} +```` + +##### DefaultValueFactory Options + +`DefaultValueFactory` can be set to a function that returns the default value: + +````csharp +property => +{ + property.DefaultValueFactory = () => DateTime.Now; +} +```` + +`options.DefaultValueFactory` has a higher priority than the `options.DefaultValue` . + +> Tip: Use `DefaultValueFactory` option only if the default value may change over the time (like `DateTime.Now` in this example). If it is a constant value, then use the `DefaultValue` option. + +### Validation + +Entity extension system allows you to define validation for extension properties in a few ways. + +#### Data Annotation Attributes + +`Attributes` is a list of attributes associated to this property. The example code below adds two [data annotation validation attributes](https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation) to the property: + +````csharp +property => +{ + property.Attributes.Add(new RequiredAttribute()); + property.Attributes.Add(new StringLengthAttribute(64) {MinimumLength = 4}); +} +```` + +When you run the application, you see that the validation works out of the box: + +![add-new-propert-to-user-form](images/add-new-property-to-user-form-validation-error.png) + +Since we've added the `RequiredAttribute`, it doesn't allow to left it blank. The validation system works; + +* On the user interface (with automatic localization). +* On the HTTP API. Even if you directly perform an HTTP request, you get validation errors with a proper HTTP status code. +* On the `SetProperty(...)` method on the entity (see [the document](Entities.md) if you wonder what is the `SetProperty()` method). + +So, it automatically makes a full stack validation. + +> See the [ASP.NET Core MVC Validation document](https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation) to learn more about the attribute based validation. + +##### Default Validation Attributes + +There are some attributes **automatically added** when you create certain type of properties; + +* `RequiredAttribute` is added for **non nullable** primitive property types (e.g. `int`, `bool`, `DateTime`...) and `enum` types. If you want to allow nulls, make the property nullable (e.g. `int?`). +* `EnumDataTypeAttribute` is added for **enum types**, to prevent to set invalid enum values. + +Use `property.Attributes.Clear();` if you don't want these attributes. + +#### Validation Actions + +Validation actions allows you to execute a custom code to perform the validation. The example below checks if the `SocialSecurityNumber` starts with `B` and adds a validation error if so: + +````csharp +property => +{ + property.Attributes.Add(new RequiredAttribute()); + property.Attributes.Add(new StringLengthAttribute(64) {MinimumLength = 4}); + + property.Validators.Add(context => + { + if (((string) context.Value).StartsWith("B")) + { + context.ValidationErrors.Add( + new ValidationResult( + "Social security number can not start with the letter 'B', sorry!", + new[] {"extraProperties.SocialSecurityNumber"} + ) + ); + } + }); + +} +```` + +Using a `RegularExpressionAttribute` might be better in this case, but this is just an example. Anyway, if you enter a value starts with the letter `B` you get the following error **while saving the form**: + +![add-new-propert-to-user-form](images/add-new-property-to-user-form-validation-error-custom.png) + +##### The Context Object + +The `context` object has useful properties that can be used in your custom validation action. For example, you can use the `context.ServiceProvider` to resolve services from the [dependency injection system](Dependency-Injection.md). The example below gets the localizer and adds a localized error message: + +````csharp +if (((string) context.Value).StartsWith("B")) +{ + var localizer = context.ServiceProvider + .GetRequiredService>(); + + context.ValidationErrors.Add( + new ValidationResult( + localizer["SocialSecurityNumberCanNotStartWithB"], + new[] {"extraProperties.SocialSecurityNumber"} + ) + ); +} +```` + +>`context.ServiceProvider` is nullable! It can be `null` only if you use the `SetProperty(...)` method on the object. Because DI system is not available on this time. While this is a rare case, you should perform a fallback logic when `context.ServiceProvider` is `null`. For this example, you would add a non-localized error message. This is not a problem since setting an invalid value to a property generally is a programmer mistake and you mostly don't need to localization in this case. In any way, you would not be able to use localization even in a regular property setter. But, if you are serious about localization, you can throw a business exception (see the [exception handling document](https://docs.abp.io/en/abp/latest/Exception-Handling) to learn how to localize a business exception). + +### UI Visibility + +When you define a property, it appears on the data table, create and edit forms on the related UI page. However, you can control each one individually. Example: + +````csharp +property => +{ + property.UI.OnTable.IsVisible = false; + //...other configurations +} +```` + +Use `property.UI.OnCreateForm` and `property.UI.OnEditForm` to control forms too. If a property is required, but not added to the create form, you definitely get a validation exception, so use this option carefully. But a required property may not be in the edit form if that's your requirement. + +### HTTP API Availability + +Even if you disable a property on UI, it can be still available through the HTTP API. By default, a property is available on all APIs. + +Use the `property.Api` options to make a property unavailable in some API endpoints. + +````csharp +property => +{ + property.Api.OnUpdate.IsAvailable = false; +} +```` + +In this example, Update HTTP API will not allow to set a new value to this property. In this case, you also want to disable this property on the edit form: + +````csharp +property => +{ + property.Api.OnUpdate.IsAvailable = false; + property.UI.OnEditForm.IsVisible = false; +} +```` + +In addition to the `property.Api.OnUpdate`, you can set `property.Api.OnCreate` and `property.Api.OnGet` for a fine control the API endpoint. + +## Special Types + +### Enum + +Module extension system naturally supports the `enum` types. + +An example enum type: + +````csharp +public enum UserType +{ + Regular, + Moderator, + SuperUser +} +```` + +You can add enum properties just like others: + +````csharp +user.AddOrUpdateProperty("Type"); +```` + +An enum properties is shown as combobox (select) in the create/edit forms: + +![add-new-property-enum](images/add-new-property-enum.png) + +#### Localization + +Enum member name is shown on the table and forms by default. If you want to localize it, just create a new entry on your [localization](https://docs.abp.io/en/abp/latest/Localization) file: + +````json +"UserType.SuperUser": "Super user" +```` + +One of the following names can be used as the localization key: + +* `Enum:UserType.SuperUser` +* `UserType.SuperUser` +* `SuperUser` + +Localization system searches for the key with the given order. Localized text are used on the table and the create/edit forms. + +## Database Mapping + +For relational databases, all extension property values are stored in a single field in the table: + +![add-new-propert-to-user-database-extra-properties](images/add-new-propert-to-user-database-extra-properties.png) + +`ExtraProperties` field stores the properties as a JSON object. While that's fine for some scenarios, you may want to create a dedicated field for your new property. Fortunately, it is very easy to configure. + +If you are using the Entity Framework Core database provider, you can configure the database mapping as shown below: + +````csharp +ObjectExtensionManager.Instance + .MapEfCoreProperty( + "SocialSecurityNumber", + (entityBuilder, propertyBuilder) => + { + propertyBuilder.HasMaxLength(64); + } + ); +```` + +Write this inside the `YourProjectNameEfCoreEntityExtensionMappings` class in your `.EntityFrameworkCore` project. Then you need to use the standard `Add-Migration` and `Update-Database` commands to create a new database migration and apply the change to your database. + +Add-Migration create a new migration as shown below: + +````csharp +public partial class Added_SocialSecurityNumber_To_IdentityUser : Migration +{ + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SocialSecurityNumber", + table: "AbpUsers", + maxLength: 128, + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SocialSecurityNumber", + table: "AbpUsers"); + } +} +```` + +Once you update your database, you will see that the `AbpUsers` table has the new property as a standard table field: + +![add-new-propert-to-user-database-extra-properties](images/add-new-propert-to-user-database-field.png) + +> If you first created a property without a database table field, then you later needed to move this property to a database table field, it is suggested to execute an SQL command in your migration to copy the old values to the new field. +> +> However, if you don't make it, the ABP Framework seamlessly manages it. It uses the new database field, but fallbacks to the `ExtraProperties` field if it is null. When you save the entity, it moves the value to the new field. + +See the [Extending Entities](Customizing-Application-Modules-Extending-Entities.md) document for more. + +## More + +See the [Customizing the Modules](Customizing-Application-Modules-Guide.md) guide for an overall index for all the extensibility options. + +Here, a few things you can do: + +* You can create a second entity that maps to the same database table with the extra property as a standard class property (if you've defined the EF Core mapping). For the example above, you can add a `public string SocialSecurityNumber {get; set;}` property to the `AppUser` entity in your application, since the `AppUser` entity is mapped to the same `AbpUser` table. Do this only if you need it, since it brings more complexity to your application. +* You can override a domain or application service to perform custom logics with your new property. +* You can low level control how to add/render a field in the data table on the UI. + diff --git a/docs/en/Modules/Identity.md b/docs/en/Modules/Identity.md index a88087eaa8..8cd7bf3966 100644 --- a/docs/en/Modules/Identity.md +++ b/docs/en/Modules/Identity.md @@ -1,6 +1,6 @@ # Identity Management Module -Identity module is used to manage [organization units](Organization-Units.md), roles, users and their permissions, based on the Microsoft Identity library. +Identity module is used to manage organization units, roles, users and their permissions, based on the Microsoft Identity library. > **See [the source code](https://github.com/abpframework/abp/tree/dev/modules/identity). Documentation will come soon...** diff --git a/docs/en/Tutorials/Part-4.md b/docs/en/Tutorials/Part-4.md index 8dab28a8db..2262598544 100644 --- a/docs/en/Tutorials/Part-4.md +++ b/docs/en/Tutorials/Part-4.md @@ -53,7 +53,7 @@ This part covers the **server side** tests. There are several test projects in t Each project is used to test the related project. Test projects use the following libraries for testing: * [Xunit](https://xunit.github.io/) as the main test framework. -* [Shoudly](http://shouldly.readthedocs.io/en/latest/) as the assertion library. +* [Shoudly](https://github.com/shouldly/shouldly) as the assertion library. * [NSubstitute](http://nsubstitute.github.io/) as the mocking library. {{if DB=="EF"}} diff --git a/docs/en/UI/Angular/List-Service.md b/docs/en/UI/Angular/List-Service.md index 7cc31a46fd..016b891159 100644 --- a/docs/en/UI/Angular/List-Service.md +++ b/docs/en/UI/Angular/List-Service.md @@ -68,6 +68,50 @@ Bind `ListService` to ngx-datatable like this: ``` +## Extending query with custom variables + +You can extend the query parameter of the `ListService`'s `hookToQuery` method. + +Firstly, you should pass your own type to `ListService` as shown below: + +```typescript +constructor(public readonly list: ListService) { } +``` + +Then update the `bookStreamCreator` constant like following: + +```typescript +const bookStreamCreator = (query) => this.bookService.getList({...query, name: 'name here'}); +``` + +You can also create your params object. + +Define a variable like this: + +```typescript +booksSearchParams = {} as BooksSearchParamsDto; +``` + +Update the `bookStreamCreator` constant: + +```typescript +const bookStreamCreator = (query) => this.bookService.getList({...query, ...this.booksSearchParams}); +``` + +Then you can place inputs to the HTML: + +```html +
+ +
+``` + +`ListService` emits the hookToQuery stream when you call the `this.list.get()` method. ## Usage with Observables diff --git a/docs/en/UI/AspNetCore/Data-Table-Column-Extensions.md b/docs/en/UI/AspNetCore/Data-Table-Column-Extensions.md new file mode 100644 index 0000000000..fec0ac71fb --- /dev/null +++ b/docs/en/UI/AspNetCore/Data-Table-Column-Extensions.md @@ -0,0 +1,161 @@ +# Data Table Column Extensions for ASP.NET Core UI + +## Introduction + +Data table column extension system allows you to add a **new table column** on the user interface. The example below adds a new column with the "Social security no" title: + +![user-action-extension-click-me](../../images/table-column-extension-example.png) + +You can use the standard column options to fine control the table column. + +> Note that this is a low level API to find control the table column. If you want to show an extension property on the table, see the [module entity extension](../../Module-Entity-Extensions.md) document. + +## How to Set Up + +### Create a JavaScript File + +First, add a new JavaScript file to your solution. We added inside the `/Pages/Identity/Users` folder of the `.Web` project: + +![user-action-extension-on-solution](../../images/user-action-extension-on-solution.png) + +Here, the content of this JavaScript file: + +```js +abp.ui.extensions.tableColumns + .get('identity.user') + .addContributor(function (columnList) { + columnList.addTail({ //add as the last column + title: 'Social security no', + data: 'extraProperties.SocialSecurityNumber', + orderable: false, + render: function (data, type, row) { + if (row.extraProperties.SocialSecurityNumber) { + return '' + + row.extraProperties.SocialSecurityNumber + + ''; + } else { + return 'undefined'; + } + } + }); + }); +``` + +This example defines a custom `render` function to return a custom HTML to render in the column. + +### Add the File to the User Management Page + +Then you need to add this JavaScript file to the user management page. You can take the power of the [Bundling & Minification system](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Bundling-Minification). + +Write the following code inside the `ConfigureServices` of your module class: + +```csharp +Configure(options => +{ + options.ScriptBundles.Configure( + typeof(Volo.Abp.Identity.Web.Pages.Identity.Users.IndexModel).FullName, + bundleConfiguration => + { + bundleConfiguration.AddFiles( + "/Pages/Identity/Users/my-user-extensions.js" + ); + }); +}); +``` + +This configuration adds `my-user-extensions.js` to the user management page of the Identity Module. `typeof(Volo.Abp.Identity.Web.Pages.Identity.Users.IndexModel).FullName` is the name of the bundle in the user management page. This is a common convention used for all the ABP Commercial modules. + +### Rendering the Column + +This example assumes that you've defined a `SocialSecurityNumber` extra property using the [module entity extension](../../Module-Entity-Extensions.md) system. However; + +* You can add a new column that is related to an existing property of the user (that was not added to the table by default). Example: + +````js +abp.ui.extensions.tableColumns + .get('identity.user') + .addContributor(function (columnList) { + columnList.addTail({ + title: 'Phone confirmed?', + data: 'phoneNumberConfirmed', + render: function (data, type, row) { + if (row.phoneNumberConfirmed) { + return 'YES'; + } else { + return 'NO'; + } + } + }); + }); +```` + +* You can add a new custom column that is not related to any entity property, but a completely custom information. Example: + +````js +abp.ui.extensions.tableColumns + .get('identity.user') + .addContributor(function (columnList) { + columnList.addTail({ + title: 'Custom column', + data: {}, + orderable: false, + render: function (data) { + if (data.phoneNumber) { + return "call: " + data.phoneNumber; + } else { + return ''; + } + } + }); + }); +```` + +## API + +This section explains details of the `abp.ui.extensions.tableColumns` JavaScript API. + +### abp.ui.extensions.tableColumns.get(entityName) + +This method is used to access the table columns for an entity of a specific module. It takes one parameter: + +* **entityName**: The name of the entity defined by the related module. + +### abp.ui.extensions.tableColumns.get(entityName).columns + +The `columns` property is used to retrieve a [doubly linked list](../Common/Utils/Linked-List.md) of previously defined columns for a table. All contributors are executed in order to prepare the final column list. This is normally called by the modules to show the columns in the table. However, you can use it if you are building your own extensible UIs. + +### abp.ui.extensions.tableColumns.get(entityName).addContributor(contributeCallback [, order]) + +The `addContributor` method covers all scenarios, e.g. you want to add your column in a different position in the list, change or remove an existing column. `addContributor` has the following parameters: + +* **contributeCallback**: A callback function that is called whenever the column list should be created. You can freely modify the column list inside this callback method. +* **order** (optional): The order of the callback in the callback list. Your callback is added to the end of the list (so, you have opportunity to modify columns added by the previous contributors). You can set it `0` to add your contributor as the first item. + +#### Example + +```js +var myColumnDefinition = { + title: 'Custom column', + data: {}, + orderable: false, + render: function(data) { + if (data.phoneNumber) { + return "call: " + data.phoneNumber; + } else { + return ''; + } + } +}; + +abp.ui.extensions.tableColumns + .get('identity.user') + .addContributor(function (columnList) { + // Remove an item from actionList + columnList.dropHead(); + + // Add a new item to the actionList + columnList.addHead(myColumnDefinition); + }); +``` + +> `columnList` is [linked list](../Common/Utils/Linked-List.md). You can use its methods to build a list of columns however you need. diff --git a/docs/en/UI/AspNetCore/Data-Tables.md b/docs/en/UI/AspNetCore/Data-Tables.md index a9dbf1eecf..b97d49d562 100644 --- a/docs/en/UI/AspNetCore/Data-Tables.md +++ b/docs/en/UI/AspNetCore/Data-Tables.md @@ -105,6 +105,32 @@ The `abp.libs.datatables.createAjax` method (used in the example above) adapts r This works automatically, so most of the times you don't need to know how it works. See the [DTO document](../../Data-Transfer-Objects.md) if you want to learn more about `IPagedAndSortedResultRequest`, `IPagedResult` and other standard interfaces and base DTO classes those are used in client to server communication. +The `createAjax` also supports you to customize request parameters and handle the responses. + +**Example:** + +````csharp +var inputAction = function () { + return { + id: $('#Id').val(), + name: $('#Name').val(), + }; +}; + +var responseCallback = function(result) { + + // your custom code. + + return { + recordsTotal: result.totalCount, + recordsFiltered: result.totalCount, + data: result.items + }; +}; + +ajax: abp.libs.datatables.createAjax(acme.bookStore.books.book.getList, inputAction, responseCallback) +```` + ### Row Actions `rowAction` is an option defined by the ABP Framework to the column definitions to show a drop down button to take actions for a row in the table. @@ -260,4 +286,4 @@ Assuming that the possible values for a column data is `f` and `m`, the `gender` ## Other Data Grids -You can use any library you like. For example, [see this article](https://community.abp.io/articles/using-devextreme-components-with-the-abp-framework-zb8z7yqv) to learn how to use DevExtreme Data Grid in your applications. \ No newline at end of file +You can use any library you like. For example, [see this article](https://community.abp.io/articles/using-devextreme-components-with-the-abp-framework-zb8z7yqv) to learn how to use DevExtreme Data Grid in your applications. diff --git a/docs/en/UI/AspNetCore/Entity-Action-Extensions.md b/docs/en/UI/AspNetCore/Entity-Action-Extensions.md new file mode 100644 index 0000000000..f6e865375d --- /dev/null +++ b/docs/en/UI/AspNetCore/Entity-Action-Extensions.md @@ -0,0 +1,108 @@ +# Entity Action Extensions for ASP.NET Core UI + +## Introduction + +Entity action extension system allows you to add a **new action** to the action menu for an entity. A **Click Me** action was added to the *User Management* page below: + +![user-action-extension-click-me](../../images/user-action-extension-click-me.png) + +You can take any action (open a modal, make an HTTP API call, redirect to another page... etc) by writing your custom code. You can access to the current entity in your code. + +## How to Set Up + +In this example, we will add a "Click Me!" action and execute a JavaScript code for the user management page of the [Identity Module](../../Modules/Identity.md). + +### Create a JavaScript File + +First, add a new JavaScript file to your solution. We added inside the `/Pages/Identity/Users` folder of the `.Web` project: + +![user-action-extension-on-solution](../../images/user-action-extension-on-solution.png) + +Here, the content of this JavaScript file: + +```js +var clickMeAction = { + text: 'Click Me!', + action: function(data) { + //TODO: Write your custom code + alert(data.record.userName); + } +}; + +abp.ui.extensions.entityActions + .get('identity.user') + .addContributor(function(actionList) { + actionList.addTail(clickMeAction); + }); +``` + +In the `action` function, you can do anything you need. See the API section for a detailed usage. + +### Add the File to the User Management Page + +Then you need to add this JavaScript file to the user management page. You can take the power of the [Bundling & Minification System](Bundling-Minification.md). + +Write the following code inside the `ConfigureServices` of your module class: + +```csharp +Configure(options => +{ + options.ScriptBundles.Configure( + typeof(Volo.Abp.Identity.Web.Pages.Identity.Users.IndexModel).FullName, + bundleConfiguration => + { + bundleConfiguration.AddFiles( + "/Pages/Identity/Users/my-user-extensions.js" + ); + }); +}); +``` + +This configuration adds `my-user-extensions.js` to the user management page of the Identity Module. `typeof(Volo.Abp.Identity.Web.Pages.Identity.Users.IndexModel).FullName` is the name of the bundle in the user management page. This is a common convention used for all the ABP Commercial modules. + +That's all. Run your application to see the result. + +## API + +This section explains details of the `abp.ui.extensions.entityActions` JavaScript API. + +### abp.ui.extensions.entityActions.get(entityName) + +This method is used to access the entity actions of a specific module. It takes one parameter: + +* **entityName**: The name of the entity defined by the related module. + +### abp.ui.extensions.entityActions.get(entityName).actions + +The `actions` property is used to retrieve a [doubly linked list](../Common/Utils/Linked-List.md) of previously defined actions for an entity. All contributors are executed in order to prepare the final actions list. This is normally called by the modules to show the actions in the grid. However, you can use it if you are building your own extensible UIs. + +### abp.ui.extensions.entityActions.get(entityName).addContributor(contributeCallback) + +The `addContributor` method covers all scenarios, e.g. you want to add your action in a different position in the list, change or remove an existing action item. `addContributor` with the following parameter: + +* **contributeCallback**: A callback function that is called whenever the action list should be created. You can freely modify the action list inside this callback method. + +#### Example + +```js +var clickMe2Action = { + text: 'Click Me 2!', + icon: 'fas fa-hand-point-right', + action: function(data) { + //TODO: Write your custom code + alert(data.record.userName); + } +}; + +abp.ui.extensions.entityActions + .get('identity.user') + .addContributor(function(actionList) { + // Remove an item from actionList + actionList.dropHead(); + + // Add the new item to the actionList + actionList.addHead(clickMe2Action); + }); +``` + +> `actionList` is [linked list](../Common/Utils/Linked-List.md). You can use its methods to build a list of columns however you need. diff --git a/docs/en/UI/AspNetCore/Theming.md b/docs/en/UI/AspNetCore/Theming.md index 8c680973b8..85acf65433 100644 --- a/docs/en/UI/AspNetCore/Theming.md +++ b/docs/en/UI/AspNetCore/Theming.md @@ -32,7 +32,7 @@ All the themes must depend on the [@abp/aspnetcore.mvc.ui.theme.shared](https:// * [Twitter Bootstrap](https://getbootstrap.com/) as the fundamental HTML/CSS framework. * [JQuery](https://jquery.com/) for DOM manipulation. * [DataTables.Net](https://datatables.net/) for data grids. -* [JQuery Validation](https://jqueryvalidation.org/) for client side & [unobtrusive](https://github.com/aspnet/jquery-validation-unobtrusive) validation +* [JQuery Validation](https://github.com/jquery-validation/jquery-validation) for client side & [unobtrusive](https://github.com/aspnet/jquery-validation-unobtrusive) validation * [FontAwesome](https://fontawesome.com/) as the fundamental CSS font library. * [SweetAlert](https://sweetalert.js.org/) to show fancy alert message and confirmation dialogs. * [Toastr](https://github.com/CodeSeven/toastr) to show toast notifications. diff --git a/docs/en/UI/Blazor/Authentication.md b/docs/en/UI/Blazor/Authentication.md index 6c1cdb31f5..9dc34ebce5 100644 --- a/docs/en/UI/Blazor/Authentication.md +++ b/docs/en/UI/Blazor/Authentication.md @@ -1,3 +1,11 @@ # Blazor UI: Authentication -TODO \ No newline at end of file +The [application startup template](../../Startup-Templates/Application.md) is properly configured to use OpenId Connect to authenticate the user through the server side login form; + +* When the Blazor application needs to authenticate, it is redirected to the server side. +* Users can enter username & password to login if they already have an account. If not, they can use the register form to create a new user. They can also use forgot password and other features. The server side uses IdentityServer4 to handle the authentication. +* Finally, they are redirected back to the Blazor application to complete the login process. + +This is a typical and recommended approach to implement authentication in Single-Page Applications. The client side configuration is done in the startup template, so you can change it. + +See the [Blazor Security document](https://docs.microsoft.com/en-us/aspnet/core/blazor/security) to understand and customize the authentication process. \ No newline at end of file diff --git a/docs/en/UI/Blazor/Authorization.md b/docs/en/UI/Blazor/Authorization.md new file mode 100644 index 0000000000..7325c8e57b --- /dev/null +++ b/docs/en/UI/Blazor/Authorization.md @@ -0,0 +1,75 @@ +# Blazor UI: Authorization + +Blazor applications can use the same authorization system and permissions defined in the server side. + +> This document is only for authorizing on the Blazor UI. See the [Server Side Authorization](../../Authorization.md) to learn how to define permissions and control the authorization system. + +## Basic Usage + +> ABP Framework is **100% compatible** with the Authorization infrastructure provided by the Blazor. See the [Blazor Security Document](https://docs.microsoft.com/en-us/aspnet/core/blazor/security/) to learn all authorization options. This section **only shows some common scenarios**. + +### Authorize Attribute + +`[Authorize]` attribute can be used to show a page only to the authenticated users. + +````csharp +@page "/" +@attribute [Authorize] + +You can only see this if you're signed in. +```` + +The `[Authorize]` attribute also supports role-based or policy-based authorization. For example, you can check permissions defined in the server side: + +````csharp +@page "/" +@attribute [Authorize("MyPermission")] + +You can only see this if you have the necessary permission. +```` + +### AuthorizeView + +`AuthorizeView` component can be used in a page/component to conditionally render a part of the content: + +````html + +

You can only see this if you satisfy the "MyPermission" policy.

+
+```` + +### IAuthorizationService + +`IAuthorizationService` can be injected and used to programmatically check permissions: + +````csharp +public partial class Index +{ + protected override async Task OnInitializedAsync() + { + if (await AuthorizationService.IsGrantedAsync("MyPermission")) + { + //... + } + } +} +```` + +If your component directly or indirectly inherits from the `AbpComponentBase`, `AuthorizationService` becomes pre-injected and ready to use. If not, you can always [inject](../../Dependency-Injection.md) the `IAuthorizationService` yourself. + +`IAuthorizationService` can also be used in the view side where `AuthorizeView` component is not enough. + +There are some useful extension methods for the `IAuthorizationService`: + +* `IsGrantedAsync` simply returns `true` or `false` for the given policy/permission. +* `CheckAsync` checks and throws `AbpAuthorizationException` if given policy/permission hasn't granted. You don't have to handle these kind of exceptions since ABP Framework automatically [handles errors](Error-Handling.md). +* `AuthorizeAsync` returns `AuthorizationResult` as the standard way provided by the ASP.NET Core authorization system. + +> See the [Blazor Security Document](https://docs.microsoft.com/en-us/aspnet/core/blazor/security/) to learn all authorization options + +## See Also + +* [Authorization](../../Authorization.md) (server side) +* [Blazor Security](https://docs.microsoft.com/en-us/aspnet/core/blazor/security/) (Microsoft documentation) +* [ICurrentUser Service](CurrentUser.md) + diff --git a/docs/en/UI/Blazor/CurrentTenant.md b/docs/en/UI/Blazor/CurrentTenant.md new file mode 100644 index 0000000000..0ccee9966c --- /dev/null +++ b/docs/en/UI/Blazor/CurrentTenant.md @@ -0,0 +1,23 @@ +# Blazor UI: Current Tenant + +`ICurrentTenant` service can be used to get information about the current tenant in a [multi-tenant](../../Multi-Tenancy.md) application. `ICurrentTenant` defines the following properties; + +* `Id` (`Guid`): Id of the current tenant. Can be `null` if the current user is a host user or the tenant could not be determined. +* `Name` (`string`): Name of the current tenant. Can be `null` if the current user is a host user or the tenant could not be determined. +* `IsAvailable` (`bool`): Returns `true` if the `Id` is not `null`. + +**Example: Show the current tenant name on a page** + +````csharp +@page "/" +@using Volo.Abp.MultiTenancy +@inject ICurrentTenant CurrentTenant +@if (CurrentTenant.IsAvailable) +{ +

Current tenant name: @CurrentTenant.Name

+} +```` + +## See Also + +* [Multi-Tenancy](../../Multi-Tenancy.md) \ No newline at end of file diff --git a/docs/en/UI/Blazor/CurrentUser.md b/docs/en/UI/Blazor/CurrentUser.md new file mode 100644 index 0000000000..d0d761420a --- /dev/null +++ b/docs/en/UI/Blazor/CurrentUser.md @@ -0,0 +1,22 @@ +# Blazor UI: Current User + +`ICurrentUser` service is used to obtain information about the currently authenticated user. Inject the `ICurrentUser` into any component/page and use its properties and methods. + +**Example: Show username & email on a page** + +````csharp +@page "/" +@using Volo.Abp.Users +@inject ICurrentUser CurrentUser +@if (CurrentUser.IsAuthenticated) +{ +

Welcome @CurrentUser.UserName

+} +```` + +> If you (directly or indirectly) derived your component from the `AbpComponentBase`, you can directly use the base `CurrentUser` property. + +`ICurrentUser` provides `Id`, `Name`, `SurName`, `Email`, `Roles` and some other properties. + +> See the [Server Side Current User](../../CurrentUser) service for more information. + diff --git a/docs/en/UI/Blazor/Error-Handling.md b/docs/en/UI/Blazor/Error-Handling.md new file mode 100644 index 0000000000..f43456e3a7 --- /dev/null +++ b/docs/en/UI/Blazor/Error-Handling.md @@ -0,0 +1,62 @@ +# Blazor UI: Error Handling + +Blazor, by default, shows a yellow line at the bottom of the page if any unhandled exception occurs. However, this is not useful in a real application. + +ABP provides an automatic error handling system for the Blazor UI. + +* Handles all unhandled exceptions and shows nice and useful messages to the user. +* It distinguishes different kind of exceptions. Hides internal/technical error details from the user (shows a generic error message in these cases). +* It is well integrated to the [server side exception handling](../../Exception-Handling.md) system. + +## Basic Usage + +There are different type of `Exception` classes handled differently by the ABP Framework. + +### UserFriendlyException + +`UserFriendlyException` is a special type of exception. You can directly show a error message dialog to the user by throwing such an exception. + +**Example** + +````csharp +@page "/" +@using Volo.Abp + + + +@code +{ + private void TestException() + { + throw new UserFriendlyException("A user friendly error message!"); + } +} +```` + +ABP automatically handle the exception and show an error message to the user: + +![blazor-user-friendly-exception](../../images/blazor-user-friendly-exception.png) + +> You can derive from `UserFriendlyException` or directly implement `IUserFriendlyException` interface to create your own `Exception` class if you need. + +> You can use the [localization system](Localization.md) to show localized error messages. + +### BusinessException and Other Exception Types + +See the [exception handling document](../../Exception-Handling.md) to understand different kind of Exception class and interfaces and other capabilities of the Exception Handling system. + +## Generic Errors + +If the thrown `Exception` is not a special type, it is considered as generic error and a generic error message is shown to the user: + +![blazor-generic-exception-message](../../images/blazor-generic-exception-message.png) + +> All error details (including stack trace) are still written in the browser's console. + +## Server Side Errors + +Errors (like Validation, Authorization and User Friendly Errors) sent by the server are processed as you expect and properly shown to the user. So, error handling system works end to end without need to manually handle exceptions or manually transfer server-to-client error messages. + +## See Also + +* [Exception Handling System](../../Exception-Handling.md) \ No newline at end of file diff --git a/docs/en/UI/Blazor/Overall.md b/docs/en/UI/Blazor/Overall.md index cf8287f0de..a249dd354b 100644 --- a/docs/en/UI/Blazor/Overall.md +++ b/docs/en/UI/Blazor/Overall.md @@ -150,6 +150,12 @@ ABP makes this possible by auto registering components to and resolving the comp Resolving a component from the Dependency Injection system makes it possible to easily replace components of a depended module. +## Error Handling + +Blazor, by default, shows a yellow line at the bottom of the page if any unhandled exception occurs. However, this is not useful in a real application. + +ABP provides an [automatic error handling system](Error-Handling.md) for the Blazor UI. + ## Customization While the theme and some modules come as NuGet packages, you can still replace/override and customize them on need. See the [Customization / Overriding Components](Customization-Overriding-Components.md) document. \ No newline at end of file diff --git a/docs/en/UI/Blazor/Page-Header.md b/docs/en/UI/Blazor/Page-Header.md new file mode 100644 index 0000000000..2c7921bbd2 --- /dev/null +++ b/docs/en/UI/Blazor/Page-Header.md @@ -0,0 +1,3 @@ +# Blazor UI: Page Header + +TODO \ No newline at end of file diff --git a/docs/en/UI/Blazor/Routing.md b/docs/en/UI/Blazor/Routing.md new file mode 100644 index 0000000000..31a5637b51 --- /dev/null +++ b/docs/en/UI/Blazor/Routing.md @@ -0,0 +1,24 @@ +# Blazor UI: Routing + +Blazor has its own [routing system](https://docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing) and you can use it in your applications. ABP doesn't add any new feature to it, except one small improvement for the [modular development](../../Module-Development-Basics.md). + +## AbpRouterOptions + +Blazor `Router` component requires to define `AdditionalAssemblies` when you have components in assemblies/projects other than the main application's entrance assembly. So, if you want to create razor class libraries as ABP modules, you typically want to add the module's assembly to the `AdditionalAssemblies`. In this case, you need to add your module's assembly to the `AbpRouterOptions`. + +**Example** + +````csharp +Configure(options => +{ + options.AdditionalAssemblies.Add(typeof(MyBlazorModule).Assembly); +}); +```` + +Write this code in the `ConfigureServices` method of your [module](../../Module-Development-Basics.md). + +`AbpRouterOptions` has another property, `AppAssembly`, which should be the entrance assembly of the application and typically set in the final application's module. If you've created your solution with the [application startup template](../../Startup-Templates/Application.md), it is already configured for you. + +## See Also + +* [Blazor Routing](https://docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing) (Microsoft Documentation) \ No newline at end of file diff --git a/docs/en/UI/Blazor/Testing.md b/docs/en/UI/Blazor/Testing.md new file mode 100644 index 0000000000..08562c5861 --- /dev/null +++ b/docs/en/UI/Blazor/Testing.md @@ -0,0 +1,3 @@ +# Blazor: Testing + +Coming soon. \ No newline at end of file diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 197bbaf988..dcaf236fa9 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -634,39 +634,76 @@ "text": "Localization", "path": "UI/Blazor/Localization.md" }, - { - "text": "Settings", - "path": "UI/Blazor/Settings.md" - }, - { - "text": "Notification", - "path": "UI/Blazor/Notification.md" - }, - { - "text": "Message", - "path": "UI/Blazor/Message.md" - }, { "text": "Theming", - "path": "UI/Blazor/Theming.md", "items": [ + { + "text": "Overall", + "path": "UI/Blazor/Theming.md" + }, { "text": "The Basic Theme", "path": "UI/Blazor/Basic-Theme.md" + }, + { + "text": "Branding", + "path": "UI/Blazor/Branding.md" + }, + { + "text": "Page Header", + "path": "UI/Blazor/Page-Header.md" + }, + { + "text": "Toolbars", + "path": "UI/Blazor/Toolbars.md" } ] }, { - "text": "Toolbars", - "path": "UI/Blazor/Toolbars.md" + "text": "Security", + "items": [ + { + "text": "Authentication", + "path": "UI/Blazor/Authentication.md" + }, + { + "text": "Authorization", + "path": "UI/Blazor/Authorization.md" + } + ] }, { - "text": "Page Alerts", - "path": "UI/Blazor/Page-Alerts.md" + "text": "Services", + "items": [ + { + "text": "Current User", + "path": "UI/Blazor/CurrentUser.md" + }, + { + "text": "Current Tenant", + "path": "UI/Blazor/CurrentTenant.md" + }, + { + "text": "Notification", + "path": "UI/Blazor/Notification.md" + }, + { + "text": "Message", + "path": "UI/Blazor/Message.md" + }, + { + "text": "Page Alerts", + "path": "UI/Blazor/Page-Alerts.md" + } + ] }, { - "text": "Branding", - "path": "UI/Blazor/Branding.md" + "text": "Settings", + "path": "UI/Blazor/Settings.md" + }, + { + "text": "Error Handling", + "path": "UI/Blazor/Error-Handling.md" }, { "text": "Customization / Overriding Components", @@ -677,8 +714,8 @@ "path": "UI/Blazor/Global-Scripts-Styles.md" }, { - "text": "Authentication", - "path": "UI/Blazor/Authentication.md" + "text": "Routing", + "path": "UI/Blazor/Routing.md" } ] }, diff --git a/docs/en/images/add-new-propert-to-user-database-extra-properties.png b/docs/en/images/add-new-propert-to-user-database-extra-properties.png new file mode 100644 index 0000000000..90c697461e Binary files /dev/null and b/docs/en/images/add-new-propert-to-user-database-extra-properties.png differ diff --git a/docs/en/images/add-new-propert-to-user-database-field.png b/docs/en/images/add-new-propert-to-user-database-field.png new file mode 100644 index 0000000000..334ba0aa35 Binary files /dev/null and b/docs/en/images/add-new-propert-to-user-database-field.png differ diff --git a/docs/en/images/add-new-property-enum.png b/docs/en/images/add-new-property-enum.png new file mode 100644 index 0000000000..34a14b1bfb Binary files /dev/null and b/docs/en/images/add-new-property-enum.png differ diff --git a/docs/en/images/add-new-property-to-user-form-validation-error-custom.png b/docs/en/images/add-new-property-to-user-form-validation-error-custom.png new file mode 100644 index 0000000000..6bb1799e19 Binary files /dev/null and b/docs/en/images/add-new-property-to-user-form-validation-error-custom.png differ diff --git a/docs/en/images/add-new-property-to-user-form-validation-error.png b/docs/en/images/add-new-property-to-user-form-validation-error.png new file mode 100644 index 0000000000..dd2eb8ad1d Binary files /dev/null and b/docs/en/images/add-new-property-to-user-form-validation-error.png differ diff --git a/docs/en/images/add-new-property-to-user-form.png b/docs/en/images/add-new-property-to-user-form.png new file mode 100644 index 0000000000..bc12a6d5ad Binary files /dev/null and b/docs/en/images/add-new-property-to-user-form.png differ diff --git a/docs/en/images/add-new-property-to-user-table.png b/docs/en/images/add-new-property-to-user-table.png new file mode 100644 index 0000000000..a2a15087cc Binary files /dev/null and b/docs/en/images/add-new-property-to-user-table.png differ diff --git a/docs/en/images/blazor-generic-exception-message.png b/docs/en/images/blazor-generic-exception-message.png new file mode 100644 index 0000000000..5e128003cf Binary files /dev/null and b/docs/en/images/blazor-generic-exception-message.png differ diff --git a/docs/en/images/blazor-user-friendly-exception.png b/docs/en/images/blazor-user-friendly-exception.png new file mode 100644 index 0000000000..fa2a70d931 Binary files /dev/null and b/docs/en/images/blazor-user-friendly-exception.png differ diff --git a/docs/en/images/table-column-extension-example.png b/docs/en/images/table-column-extension-example.png new file mode 100644 index 0000000000..84d87bf46c Binary files /dev/null and b/docs/en/images/table-column-extension-example.png differ diff --git a/docs/en/images/user-action-extension-click-me.png b/docs/en/images/user-action-extension-click-me.png new file mode 100644 index 0000000000..4046630f48 Binary files /dev/null and b/docs/en/images/user-action-extension-click-me.png differ diff --git a/docs/en/images/user-action-extension-on-solution.png b/docs/en/images/user-action-extension-on-solution.png new file mode 100644 index 0000000000..5f58d3f302 Binary files /dev/null and b/docs/en/images/user-action-extension-on-solution.png differ diff --git a/docs/zh-Hans/CLI.md b/docs/zh-Hans/CLI.md index 3390ce99b3..4c63dcd818 100644 --- a/docs/zh-Hans/CLI.md +++ b/docs/zh-Hans/CLI.md @@ -126,6 +126,7 @@ abp update [options] * `--solution-path` 或 `-sp`: 指定解决方案路径/目录. 默认使用当前目录 * `--solution-name` 或 `-sn`: 指定解决方案名称. 默认在目录中搜索`*.sln`文件. * `--check-all`: 分别检查每个包的新版本. 默认是 `false`. +* `--version` or `-v`: 指定用于升级的版本. 如果没有指定,则使用最新版本. ### add-package diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/Branding.razor b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/Branding.razor index 4810320664..ac629423ce 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/Branding.razor +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/Branding.razor @@ -1,3 +1,3 @@ @using Volo.Abp.Ui.Branding @inject IBrandingProvider BrandingProvider -@BrandingProvider.AppName +@BrandingProvider.AppName diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpBlazorClientHttpMessageHandler.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpBlazorClientHttpMessageHandler.cs index 1b5c5893d5..84f9743a1e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpBlazorClientHttpMessageHandler.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpBlazorClientHttpMessageHandler.cs @@ -3,6 +3,8 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Configuration; using Microsoft.JSInterop; using Volo.Abp.DependencyInjection; @@ -12,14 +14,28 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly { private readonly IJSRuntime _jsRuntime; - public AbpBlazorClientHttpMessageHandler(IJSRuntime jsRuntime) + private readonly ICookieService _cookieService; + + private readonly NavigationManager _navigationManager; + + private const string AntiForgeryCookieName = "XSRF-TOKEN"; + + private const string AntiForgeryHeaderName = "RequestVerificationToken"; + + public AbpBlazorClientHttpMessageHandler( + IJSRuntime jsRuntime, + ICookieService cookieService, + NavigationManager navigationManager) { _jsRuntime = jsRuntime; + _cookieService = cookieService; + _navigationManager = navigationManager; } protected async override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { await SetLanguageAsync(request, cancellationToken); + await SetAntiForgeryTokenAsync(request); return await base.SendAsync(request, cancellationToken); } @@ -38,5 +54,28 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(selectedLanguage)); } } + + private async Task SetAntiForgeryTokenAsync(HttpRequestMessage request) + { + if (request.Method == HttpMethod.Get || request.Method == HttpMethod.Head || + request.Method == HttpMethod.Trace || request.Method == HttpMethod.Options) + { + return; + } + + var selfUri = new Uri(_navigationManager.Uri); + + if (request.RequestUri.Host != selfUri.Host || request.RequestUri.Port != selfUri.Port) + { + return; + } + + var token = await _cookieService.GetAsync(AntiForgeryCookieName); + + if (!token.IsNullOrWhiteSpace()) + { + request.Headers.Add(AntiForgeryHeaderName, token); + } + } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js index 2bbd1aa7a3..b0c4873b59 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js @@ -325,7 +325,14 @@ * AJAX extension for datatables * *************************************************************************/ (function () { - datatables.createAjax = function (serverMethod, inputAction) { + datatables.createAjax = function (serverMethod, inputAction, responseCallback) { + responseCallback = responseCallback || function(result) { + return { + recordsTotal: result.totalCount, + recordsFiltered: result.totalCount, + data: result.items + }; + } return function (requestData, callback, settings) { var input = inputAction ? inputAction(requestData, settings) : {}; @@ -359,11 +366,7 @@ if (callback) { serverMethod(input).then(function (result) { - callback({ - recordsTotal: result.totalCount, - recordsFiltered: result.totalCount, - data: result.items - }); + callback(responseCallback(result)); }); } }; diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj index 208cfa1376..ad0066db55 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Theming/StandardLayouts.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Theming/StandardLayouts.cs index 3e1b751262..338d12f531 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Theming/StandardLayouts.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Theming/StandardLayouts.cs @@ -4,6 +4,7 @@ { public const string Application = "Application"; public const string Account = "Account"; + public const string Public = "Public"; public const string Empty = "Empty"; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Theming/ThemeExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Theming/ThemeExtensions.cs index ad6e5f49d1..9583fd57cf 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Theming/ThemeExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Theming/ThemeExtensions.cs @@ -12,9 +12,14 @@ return theme.GetLayout(StandardLayouts.Account, fallbackToDefault); } + public static string GetPublicLayout(this ITheme theme, bool fallbackToDefault = true) + { + return theme.GetLayout(StandardLayouts.Public, fallbackToDefault); + } + public static string GetEmptyLayout(this ITheme theme, bool fallbackToDefault = true) { return theme.GetLayout(StandardLayouts.Empty, fallbackToDefault); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj index fde96ac65c..53e3c7f503 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj @@ -29,7 +29,7 @@ - + diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpExtraPropertiesDictionaryModelBinderProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpExtraPropertiesDictionaryModelBinderProvider.cs index 2aadddbb8b..faa490acfa 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpExtraPropertiesDictionaryModelBinderProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpExtraPropertiesDictionaryModelBinderProvider.cs @@ -23,7 +23,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ModelBinding return null; } - if (!context.Metadata.ContainerType.IsAssignableTo()) + if (context.Metadata.ContainerType == null || + !context.Metadata.ContainerType.IsAssignableTo()) { return null; } diff --git a/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs b/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs index 45650b06a4..bb820c3a83 100644 --- a/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs +++ b/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs @@ -95,7 +95,8 @@ namespace Microsoft.AspNetCore.Authorization { if (!await authorizationService.IsGrantedAsync(policyName)) { - throw new AbpAuthorizationException("Authorization failed! Given policy has not granted: " + policyName); + throw new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenPolicyHasNotGrantedWithPolicyName) + .WithData("PolicyName", policyName); } } @@ -103,7 +104,8 @@ namespace Microsoft.AspNetCore.Authorization { if (!await authorizationService.IsGrantedAsync(resource, requirement)) { - throw new AbpAuthorizationException("Authorization failed! Given requirement has not granted for given resource: " + resource); + throw new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenRequirementHasNotGrantedForGivenResource) + .WithData("ResourceName", resource); } } @@ -111,7 +113,8 @@ namespace Microsoft.AspNetCore.Authorization { if (!await authorizationService.IsGrantedAsync(resource, policy)) { - throw new AbpAuthorizationException("Authorization failed! Given policy has not granted for given resource: " + resource); + throw new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenPolicyHasNotGrantedForGivenResource) + .WithData("ResourceName", resource); } } @@ -119,7 +122,7 @@ namespace Microsoft.AspNetCore.Authorization { if (!await authorizationService.IsGrantedAsync(policy)) { - throw new AbpAuthorizationException("Authorization failed! Given policy has not granted."); + throw new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenPolicyHasNotGranted); } } @@ -127,7 +130,8 @@ namespace Microsoft.AspNetCore.Authorization { if (!await authorizationService.IsGrantedAsync(resource, requirements)) { - throw new AbpAuthorizationException("Authorization failed! Given requirements have not granted for given resource: " + resource); + throw new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenRequirementsHasNotGrantedForGivenResource) + .WithData("ResourceName", resource); } } @@ -135,7 +139,8 @@ namespace Microsoft.AspNetCore.Authorization { if (!await authorizationService.IsGrantedAsync(resource, policyName)) { - throw new AbpAuthorizationException("Authorization failed! Given polist has not granted for given resource: " + resource); + throw new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenPolicyHasNotGrantedForGivenResource) + .WithData("ResourceName", resource); } } @@ -149,4 +154,4 @@ namespace Microsoft.AspNetCore.Authorization return abpAuthorizationService; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj b/framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj index 9e355531fa..66dd574322 100644 --- a/framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj +++ b/framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj @@ -19,7 +19,12 @@ - + + + + + + diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationErrorCodes.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationErrorCodes.cs new file mode 100644 index 0000000000..0d4562eba3 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationErrorCodes.cs @@ -0,0 +1,15 @@ +namespace Volo.Abp.Authorization +{ + public static class AbpAuthorizationErrorCodes + { + public const string GivenPolicyHasNotGranted = "Volo.Authorization:010001"; + + public const string GivenPolicyHasNotGrantedWithPolicyName = "Volo.Authorization:010002"; + + public const string GivenPolicyHasNotGrantedForGivenResource = "Volo.Authorization:010003"; + + public const string GivenRequirementHasNotGrantedForGivenResource = "Volo.Authorization:010004"; + + public const string GivenRequirementsHasNotGrantedForGivenResource = "Volo.Authorization:010005"; + } +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs index b16e08a214..b4d5795b9c 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs @@ -3,17 +3,20 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Volo.Abp.Authorization.Localization; using Volo.Abp.Authorization.Permissions; using Volo.Abp.Localization; +using Volo.Abp.Localization.ExceptionHandling; using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; using Volo.Abp.Security; +using Volo.Abp.VirtualFileSystem; namespace Volo.Abp.Authorization { [DependsOn( typeof(AbpSecurityModule), - typeof(AbpLocalizationAbstractionsModule), + typeof(AbpLocalizationModule), typeof(AbpMultiTenancyModule) )] public class AbpAuthorizationModule : AbpModule @@ -38,6 +41,23 @@ namespace Volo.Abp.Authorization options.ValueProviders.Add(); options.ValueProviders.Add(); }); + + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add("en") + .AddVirtualJson("/Volo/Abp/Authorization/Localization"); + }); + + Configure(options => + { + options.MapCodeNamespace("Volo.Authorization", typeof(AbpAuthorizationResource)); + }); } private static void AutoAddDefinitionProviders(IServiceCollection services) diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/AbpAuthorizationResource.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/AbpAuthorizationResource.cs new file mode 100644 index 0000000000..2888509915 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/AbpAuthorizationResource.cs @@ -0,0 +1,10 @@ +using Volo.Abp.Localization; + +namespace Volo.Abp.Authorization.Localization +{ + [LocalizationResourceName("AbpAuthorization")] + public class AbpAuthorizationResource + { + + } +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/en.json b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/en.json new file mode 100644 index 0000000000..e7bc77c341 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/en.json @@ -0,0 +1,10 @@ +{ + "culture": "en", + "texts": { + "Volo.Authorization:010001": "Authorization failed! Given policy has not granted.", + "Volo.Authorization:010002": "Authorization failed! Given policy has not granted: {PolicyName}", + "Volo.Authorization:010003": "Authorization failed! Given policy has not granted for given resource: {ResourceName}", + "Volo.Authorization:010004": "Authorization failed! Given requirement has not granted for given resource: {ResourceName}", + "Volo.Authorization:010005": "Authorization failed! Given requirements has not granted for given resource: {ResourceName}" + } +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/tr.json b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/tr.json new file mode 100644 index 0000000000..b2d79bd949 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/tr.json @@ -0,0 +1,10 @@ +{ + "culture": "tr", + "texts": { + "Volo.Authorization:010001": "Yetkilendirme başarısız! Belirtilen izin sağlanmamış.", + "Volo.Authorization:010002": "Yetkilendirme başarısız! Bu izin sağlanmamış: {PolicyName}", + "Volo.Authorization:010003": "Yetkilendirme başarısız! Bu izin, bu kaynak için sağlanmamış: {ResourceName}", + "Volo.Authorization:010004": "Yetkilendirme başarısız! Bu kaynak belirtilen gerekliliği sağlamamış: {ResourceName}", + "Volo.Authorization:010005": "Yetkilendirme başarısız! Bu kaynak belirtilen gereklilikleri sağlamamış: {ResourceName}" + } +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/zh-Hans.json b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/zh-Hans.json new file mode 100644 index 0000000000..d0946ef6a5 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/zh-Hans.json @@ -0,0 +1,10 @@ +{ + "culture": "zh-Hans", + "texts": { + "Volo.Authorization:010001": "授权失败! 提供的策略尚未授予.", + "Volo.Authorization:010002": "授权失败! 提供的策略尚未授予: {PolicyName}", + "Volo.Authorization:010003": "授权失败! 提供的策略未授予提供的资源: {ResourceName}", + "Volo.Authorization:010004": "授权失败! 提供的要求未授予提供的资源: {ResourceName}", + "Volo.Authorization:010005": "授权失败! 提供的要求未授予提供的资源: {ResourceName}" + } +} diff --git a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj index bd5cffe848..9f028d31ee 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj +++ b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj @@ -21,7 +21,7 @@ - + diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacRegistration.cs b/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacRegistration.cs index 024fc3a258..e0f7ec50ad 100644 --- a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacRegistration.cs +++ b/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacRegistration.cs @@ -27,6 +27,7 @@ using System; using System.Reflection; using Autofac.Builder; using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Autofac; using Volo.Abp.Modularity; namespace Autofac.Extensions.DependencyInjection @@ -116,6 +117,7 @@ namespace Autofac.Extensions.DependencyInjection .RegisterGeneric(service.ImplementationType) .As(service.ServiceType) .ConfigureLifecycle(service.Lifetime) + .FindConstructorsWith(new AbpAutofacConstructorFinder()) .ConfigureAbpConventions(moduleContainer, registrationActionList); } else @@ -124,6 +126,7 @@ namespace Autofac.Extensions.DependencyInjection .RegisterType(service.ImplementationType) .As(service.ServiceType) .ConfigureLifecycle(service.Lifetime) + .FindConstructorsWith(new AbpAutofacConstructorFinder()) .ConfigureAbpConventions(moduleContainer, registrationActionList); } } diff --git a/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj b/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj index 2032464676..ec9e4c0364 100644 --- a/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj +++ b/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/framework/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AbpAutofacConstructorFinder.cs b/framework/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AbpAutofacConstructorFinder.cs new file mode 100644 index 0000000000..a9d0b736a2 --- /dev/null +++ b/framework/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AbpAutofacConstructorFinder.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Concurrent; +using System.Reflection; +using Autofac.Core.Activators.Reflection; + +namespace Volo.Abp.Autofac +{ + public class AbpAutofacConstructorFinder : IConstructorFinder + { + private const BindingFlags DeclaredOnlyPublicFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly; //Remove static constructor, BindingFlags.Static + + private readonly Func _finder; + + private static readonly ConcurrentDictionary DefaultPublicConstructorsCache = new ConcurrentDictionary(); + + public AbpAutofacConstructorFinder() + : this(GetDefaultPublicConstructors) + { + } + + public AbpAutofacConstructorFinder(Func finder) + { + _finder = finder ?? throw new ArgumentNullException(nameof(finder)); + } + + public ConstructorInfo[] FindConstructors(Type targetType) + { + return _finder(targetType); + } + + private static ConstructorInfo[] GetDefaultPublicConstructors(Type type) + { + var retval = DefaultPublicConstructorsCache.GetOrAdd(type, t => t.GetConstructors(DeclaredOnlyPublicFlags)); + + if (retval.Length == 0) + { + throw new NoConstructorsFoundException(type); + } + + return retval; + } + } +} diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs index 62e79010cc..2635294323 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs @@ -17,7 +17,7 @@ namespace Volo.Abp.BackgroundJobs protected AbpBackgroundJobWorkerOptions WorkerOptions { get; } public BackgroundJobWorker( - AbpTimer timer, + AbpAsyncTimer timer, IOptions jobOptions, IOptions workerOptions, IServiceScopeFactory serviceScopeFactory) @@ -113,4 +113,4 @@ namespace Volo.Abp.BackgroundJobs return nextTryDate; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerAdapter.cs b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerAdapter.cs index e6a65a2865..970beea3f0 100644 --- a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerAdapter.cs +++ b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerAdapter.cs @@ -34,7 +34,7 @@ namespace Volo.Abp.BackgroundWorkers.Quartz throw new ArgumentException($"{nameof(worker)} type is different from the generic type"); } - var timer = (AbpTimer) worker.GetType().GetProperty("Timer", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(worker); + var timer = (AbpAsyncTimer) worker.GetType().GetProperty("Timer", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(worker); period = timer?.Period; } else diff --git a/framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/AsyncPeriodicBackgroundWorkerBase.cs b/framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/AsyncPeriodicBackgroundWorkerBase.cs index ed48ba69ee..094c6eb7eb 100644 --- a/framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/AsyncPeriodicBackgroundWorkerBase.cs +++ b/framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/AsyncPeriodicBackgroundWorkerBase.cs @@ -11,15 +11,15 @@ namespace Volo.Abp.BackgroundWorkers public abstract class AsyncPeriodicBackgroundWorkerBase : BackgroundWorkerBase { protected IServiceScopeFactory ServiceScopeFactory { get; } - protected AbpTimer Timer { get; } + protected AbpAsyncTimer Timer { get; } protected AsyncPeriodicBackgroundWorkerBase( - AbpTimer timer, + AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory) { ServiceScopeFactory = serviceScopeFactory; Timer = timer; - Timer.Elapsed += Timer_Elapsed; + Timer.Elapsed = Timer_Elapsed; } public async override Task StartAsync(CancellationToken cancellationToken = default) @@ -34,23 +34,24 @@ namespace Volo.Abp.BackgroundWorkers await base.StopAsync(cancellationToken); } - private void Timer_Elapsed(object sender, System.EventArgs e) + private async Task Timer_Elapsed(AbpAsyncTimer timer) + { + await DoWorkAsync(); + } + + private async Task DoWorkAsync() { using (var scope = ServiceScopeFactory.CreateScope()) { try { - AsyncHelper.RunSync( - () => DoWorkAsync(new PeriodicBackgroundWorkerContext(scope.ServiceProvider)) - ); + await DoWorkAsync(new PeriodicBackgroundWorkerContext(scope.ServiceProvider)); } catch (Exception ex) { - AsyncHelper.RunSync( - () => scope.ServiceProvider - .GetRequiredService() - .NotifyAsync(new ExceptionNotificationContext(ex)) - ); + await scope.ServiceProvider + .GetRequiredService() + .NotifyAsync(new ExceptionNotificationContext(ex)); Logger.LogException(ex); } diff --git a/framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/PeriodicBackgroundWorkerBase.cs b/framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/PeriodicBackgroundWorkerBase.cs index e29dbfec6e..6ac757fef5 100644 --- a/framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/PeriodicBackgroundWorkerBase.cs +++ b/framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/PeriodicBackgroundWorkerBase.cs @@ -43,14 +43,12 @@ namespace Volo.Abp.BackgroundWorkers { try { - DoWork(new PeriodicBackgroundWorkerContext(scope.ServiceProvider)); } catch (Exception ex) { - scope.ServiceProvider - .GetRequiredService() - .NotifyAsync(new ExceptionNotificationContext(ex)); + var exceptionNotifier = scope.ServiceProvider.GetRequiredService(); + AsyncHelper.RunSync(() => exceptionNotifier.NotifyAsync(new ExceptionNotificationContext(ex))); Logger.LogException(ex); } diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/SubmitButton.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/SubmitButton.razor new file mode 100644 index 0000000000..140aa6502e --- /dev/null +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/SubmitButton.razor @@ -0,0 +1,10 @@ + diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/SubmitButton.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/SubmitButton.razor.cs new file mode 100644 index 0000000000..95cbdedd20 --- /dev/null +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/SubmitButton.razor.cs @@ -0,0 +1,73 @@ +using System; +using System.Threading.Tasks; +using Blazorise; +using Localization.Resources.AbpUi; +using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Localization; + +namespace Volo.Abp.BlazoriseUI.Components +{ + public partial class SubmitButton : ComponentBase + { + protected bool Submiting { get; set; } + + [Parameter] + public string Form { get; set; } + + [Parameter] + public ButtonType Type { get; set; } = ButtonType.Submit; + + [Parameter] + public Color Color { get; set; } = Color.Primary; + + [Parameter] + public bool PreventDefaultOnSubmit { get; set; } = true; + + [Parameter] + public bool Block { get; set; } + + [Parameter] + public bool? Disabled { get; set; } + + [Parameter] + public string SaveResourceKey { get; set; } = "Save"; + + [Parameter] + public EventCallback Clicked { get; set; } + + [Parameter] + public RenderFragment ChildContent { get; set; } + + [Inject] + protected IStringLocalizer StringLocalizer { get; set; } + + protected bool IsDisabled + => Disabled == true || Submiting; + + protected bool IsLoading + => Submiting; + + protected string SaveString + => StringLocalizer[SaveResourceKey]; + + protected virtual async Task OnClickedHandler() + { + try + { + Submiting = true; + + await Clicked.InvokeAsync(null); + } + catch (Exception) + { + throw; + } + finally + { + Submiting = false; + + await InvokeAsync(StateHasChanged); + } + } + } +} diff --git a/framework/src/Volo.Abp.BlobStoring.Aliyun/Volo.Abp.BlobStoring.Aliyun.csproj b/framework/src/Volo.Abp.BlobStoring.Aliyun/Volo.Abp.BlobStoring.Aliyun.csproj index f3f8249f50..25c486d79f 100644 --- a/framework/src/Volo.Abp.BlobStoring.Aliyun/Volo.Abp.BlobStoring.Aliyun.csproj +++ b/framework/src/Volo.Abp.BlobStoring.Aliyun/Volo.Abp.BlobStoring.Aliyun.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/src/Volo.Abp.BlobStoring.Aws/Volo.Abp.BlobStoring.Aws.csproj b/framework/src/Volo.Abp.BlobStoring.Aws/Volo.Abp.BlobStoring.Aws.csproj index 796da8aa26..d36d2bfbf3 100644 --- a/framework/src/Volo.Abp.BlobStoring.Aws/Volo.Abp.BlobStoring.Aws.csproj +++ b/framework/src/Volo.Abp.BlobStoring.Aws/Volo.Abp.BlobStoring.Aws.csproj @@ -17,8 +17,8 @@ - - + + diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo.Abp.BlobStoring.Azure.csproj b/framework/src/Volo.Abp.BlobStoring.Azure/Volo.Abp.BlobStoring.Azure.csproj index 6434e1d43c..73a8116e46 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo.Abp.BlobStoring.Azure.csproj +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo.Abp.BlobStoring.Azure.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs b/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs index 3a46c3b18e..d62411628e 100644 --- a/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs +++ b/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs @@ -1029,7 +1029,7 @@ namespace Volo.Abp.Caching protected virtual void HandleException(Exception ex) { - AsyncHelper.RunSync(() => HandleExceptionAsync(ex)); + _ = HandleExceptionAsync(ex); } protected virtual async Task HandleExceptionAsync(Exception ex) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj b/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj index 13f81e730b..c9ea67209f 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj +++ b/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj @@ -15,10 +15,10 @@ - - - - + + + + diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs index 223b354c6a..12810aebb9 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs @@ -81,22 +81,18 @@ namespace Volo.Abp.Cli.Commands using (var client = new CliHttpClient()) { - var response = await client.GetHttpResponseMessageWithRetryAsync( - url, - CancellationTokenProvider.Token, - Logger); - - if (!response.IsSuccessStatusCode) + using (var response = await client.GetHttpResponseMessageWithRetryAsync(url, CancellationTokenProvider.Token, Logger)) { - throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'"); - } + if (!response.IsSuccessStatusCode) + { + throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'"); + } - await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); - var responseContent = await response.Content.ReadAsStringAsync(); - var result = JsonSerializer.Deserialize(responseContent); - - return result; + var responseContent = await response.Content.ReadAsStringAsync(); + return JsonSerializer.Deserialize(responseContent); + } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index 01807bc0ff..75d2651cbc 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -3,18 +3,22 @@ using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Text; +using System.Text.Json; using System.Threading.Tasks; using ICSharpCode.SharpZipLib.Core; using ICSharpCode.SharpZipLib.Zip; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Cli.Args; +using Volo.Abp.Cli.Auth; +using Volo.Abp.Cli.Http; using Volo.Abp.Cli.ProjectBuilding; using Volo.Abp.Cli.ProjectBuilding.Building; using Volo.Abp.Cli.ProjectBuilding.Templates.App; using Volo.Abp.Cli.ProjectBuilding.Templates.Console; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; +using Volo.Abp.Threading; namespace Volo.Abp.Cli.Commands { @@ -25,7 +29,8 @@ namespace Volo.Abp.Cli.Commands protected TemplateProjectBuilder TemplateProjectBuilder { get; } public ITemplateInfoProvider TemplateInfoProvider { get; } - public NewCommand(TemplateProjectBuilder templateProjectBuilder, ITemplateInfoProvider templateInfoProvider) + public NewCommand(TemplateProjectBuilder templateProjectBuilder + , ITemplateInfoProvider templateInfoProvider) { TemplateProjectBuilder = templateProjectBuilder; TemplateInfoProvider = templateInfoProvider; @@ -193,7 +198,7 @@ namespace Volo.Abp.Cli.Commands Logger.LogInformation($"'{projectName}' has been successfully created to '{outputFolder}'"); - if (AppTemplateBase.IsAppTemplate(template ?? TemplateInfoProvider.GetDefault().Name)) + if (AppTemplateBase.IsAppTemplate(template ?? (await TemplateInfoProvider.GetDefaultAsync()).Name)) { var isCommercial = template == AppProTemplate.TemplateName; OpenThanksPage(uiFramework, databaseProvider, isTiered || commandLineArgs.Options.ContainsKey("separate-identity-server"), isCommercial); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs index 5fd30115e2..3173744bd0 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs @@ -34,24 +34,25 @@ namespace Volo.Abp.Cli.Commands var directory = commandLineArgs.Options.GetOrNull(Options.SolutionPath.Short, Options.SolutionPath.Long) ?? Directory.GetCurrentDirectory(); + var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long); if (updateNuget || !updateNpm) { - await UpdateNugetPackages(commandLineArgs, directory); + await UpdateNugetPackages(commandLineArgs, directory, version); } if (updateNpm || !updateNuget) { - await UpdateNpmPackages(directory); + await UpdateNpmPackages(directory, version); } } - private async Task UpdateNpmPackages(string directory) + private async Task UpdateNpmPackages(string directory, string version) { - await _npmPackagesUpdater.Update(directory); + await _npmPackagesUpdater.Update(directory, version: version); } - private async Task UpdateNugetPackages(CommandLineArgs commandLineArgs, string directory) + private async Task UpdateNugetPackages(CommandLineArgs commandLineArgs, string directory, string version) { var solution = commandLineArgs.Options.GetOrNull(Options.SolutionName.Short, Options.SolutionName.Long); @@ -66,7 +67,7 @@ namespace Volo.Abp.Cli.Commands { var solutionName = Path.GetFileName(solution).RemovePostFix(".sln"); - await _nugetPackagesVersionUpdater.UpdateSolutionAsync(solution, checkAll: checkAll); + await _nugetPackagesVersionUpdater.UpdateSolutionAsync(solution, checkAll: checkAll, version: version); Logger.LogInformation($"Volo packages are updated in {solutionName} solution."); return; @@ -78,7 +79,7 @@ namespace Volo.Abp.Cli.Commands { var projectName = Path.GetFileName(project).RemovePostFix(".csproj"); - await _nugetPackagesVersionUpdater.UpdateProjectAsync(project, checkAll: checkAll); + await _nugetPackagesVersionUpdater.UpdateProjectAsync(project, checkAll: checkAll, version: version); Logger.LogInformation($"Volo packages are updated in {projectName} project."); return; @@ -107,6 +108,7 @@ namespace Volo.Abp.Cli.Commands sb.AppendLine("-sp|--solution-path (Specify the solution path)"); sb.AppendLine("-sn|--solution-name (Specify the solution name)"); sb.AppendLine("--check-all (Check the new version of each package separately)"); + sb.AppendLine("-v|--version (default: latest version)"); sb.AppendLine(""); sb.AppendLine("Some examples:"); sb.AppendLine(""); @@ -148,6 +150,12 @@ namespace Volo.Abp.Cli.Commands { public const string Long = "check-all"; } + + public static class Version + { + public const string Short = "v"; + public const string Long = "version"; + } } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs index 3712d0be13..d853067abf 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs @@ -67,10 +67,7 @@ namespace Volo.Abp.Cli.Http }; } - if (!cancellationToken.HasValue) - { - cancellationToken = CancellationToken.None; - } + cancellationToken ??= CancellationToken.None; return await HttpPolicyExtensions .HandleTransientHttpError() diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs index 33a2e10fdf..2aeb8ed90a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs @@ -59,22 +59,18 @@ namespace Volo.Abp.Cli.Licensing using (var client = new CliHttpClient()) { - var response = await client.GetHttpResponseMessageWithRetryAsync( - url: url, - cancellationToken: CancellationTokenProvider.Token, - logger: _logger); - - if (!response.IsSuccessStatusCode) + using (var response = await client.GetHttpResponseMessageWithRetryAsync(url, CancellationTokenProvider.Token, _logger)) { - throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'"); - } + if (!response.IsSuccessStatusCode) + { + throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'"); + } - await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); - var responseContent = await response.Content.ReadAsStringAsync(); - var apiKeyResult = JsonSerializer.Deserialize(responseContent); - - return apiKeyResult; + var responseContent = await response.Content.ReadAsStringAsync(); + return JsonSerializer.Deserialize(responseContent); + } } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs index 1ecfc9e34d..057ffcc02d 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs @@ -40,13 +40,43 @@ namespace Volo.Abp.Cli.NuGet } public async Task GetLatestVersionOrNullAsync(string packageId, bool includeNightly = false, bool includeReleaseCandidates = false) + { + var versionList = await GetPackageVersionListAsync(packageId, includeNightly, includeReleaseCandidates); + + List versions; + + if (!includeNightly && !includeReleaseCandidates) + { + versions = versionList + .Select(SemanticVersion.Parse) + .OrderByDescending(v => v, new VersionComparer()).ToList(); + + versions = versions.Where(x => !x.IsPrerelease).ToList(); + } + else if (!includeNightly && includeReleaseCandidates) + { + versions = versionList + .Where(v => !v.Contains("-preview")) + .Select(SemanticVersion.Parse) + .OrderByDescending(v => v, new VersionComparer()).ToList(); + } + else + { + versions = versionList + .Select(SemanticVersion.Parse) + .OrderByDescending(v => v, new VersionComparer()).ToList(); + } + + return versions.Any() ? versions.Max() : null; + + } + + public async Task> GetPackageVersionListAsync(string packageId, bool includeNightly = false, + bool includeReleaseCandidates = false) { if (AuthService.IsLoggedIn()) { - if (_proPackageList == null) - { - _proPackageList = await GetProPackageListAsync(); - } + _proPackageList ??= await GetProPackageListAsync(); } string url; @@ -65,47 +95,16 @@ namespace Volo.Abp.Cli.NuGet using (var client = new CliHttpClient(setBearerToken: false)) { - var responseMessage = await client.GetHttpResponseMessageWithRetryAsync( + using (var responseMessage = await client.GetHttpResponseMessageWithRetryAsync( url, cancellationToken: CancellationTokenProvider.Token, logger: Logger - ); - - await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage); - - var responseContent = await responseMessage.Content.ReadAsStringAsync(); - - List versions; - - if (!includeNightly && !includeReleaseCandidates) - { - versions = JsonSerializer - .Deserialize(responseContent) - .Versions - .Select(SemanticVersion.Parse) - .OrderByDescending(v=> v, new VersionComparer()).ToList(); - - versions = versions.Where(x => !x.IsPrerelease).ToList(); - } - else if (!includeNightly && includeReleaseCandidates) + )) { - versions = JsonSerializer - .Deserialize(responseContent) - .Versions - .Where(v=> !v.Contains("-preview")) - .Select(SemanticVersion.Parse) - .OrderByDescending(v=> v, new VersionComparer()).ToList(); + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage); + var responseContent = await responseMessage.Content.ReadAsStringAsync(); + return JsonSerializer.Deserialize(responseContent).Versions; } - else - { - versions = JsonSerializer - .Deserialize(responseContent) - .Versions - .Select(SemanticVersion.Parse) - .OrderByDescending(v=> v, new VersionComparer()).ToList(); - } - - return versions.Any() ? versions.Max() : null; } } @@ -125,27 +124,28 @@ namespace Volo.Abp.Cli.NuGet var url = $"{CliUrls.WwwAbpIo}api/app/nugetPackage/proPackageNames"; - var responseMessage = await client.GetHttpResponseMessageWithRetryAsync( + using (var responseMessage = await client.GetHttpResponseMessageWithRetryAsync( url: url, cancellationToken: CancellationTokenProvider.Token, logger: Logger - ); - - if (responseMessage.IsSuccessStatusCode) + )) { - return JsonSerializer.Deserialize>(await responseMessage.Content.ReadAsStringAsync()); - } + if (responseMessage.IsSuccessStatusCode) + { + return JsonSerializer.Deserialize>(await responseMessage.Content.ReadAsStringAsync()); + } - var exceptionMessage = "Remote server returns '" + (int)responseMessage.StatusCode + "-" + responseMessage.ReasonPhrase + "'. "; - var remoteServiceErrorMessage = await RemoteServiceExceptionHandler.GetAbpRemoteServiceErrorAsync(responseMessage); + var exceptionMessage = "Remote server returns '" + (int)responseMessage.StatusCode + "-" + responseMessage.ReasonPhrase + "'. "; + var remoteServiceErrorMessage = await RemoteServiceExceptionHandler.GetAbpRemoteServiceErrorAsync(responseMessage); - if (remoteServiceErrorMessage != null) - { - exceptionMessage += remoteServiceErrorMessage; - } + if (remoteServiceErrorMessage != null) + { + exceptionMessage += remoteServiceErrorMessage; + } - Logger.LogError(exceptionMessage); - return null; + Logger.LogError(exceptionMessage); + return null; + } } public class NuGetVersionResultDto @@ -154,4 +154,4 @@ namespace Volo.Abp.Cli.NuGet public List Versions { get; set; } } } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ITemplateInfoProvider.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ITemplateInfoProvider.cs index 5330bc9962..55db4cd11a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ITemplateInfoProvider.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ITemplateInfoProvider.cs @@ -1,10 +1,11 @@ -using Volo.Abp.Cli.ProjectBuilding.Building; +using System.Threading.Tasks; +using Volo.Abp.Cli.ProjectBuilding.Building; namespace Volo.Abp.Cli.ProjectBuilding { public interface ITemplateInfoProvider { - TemplateInfo GetDefault(); + Task GetDefaultAsync(); TemplateInfo Get(string name); } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs index 7a4df335fe..2aefcfd1a9 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs @@ -1,18 +1,44 @@ using System; +using System.Text.Json; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Cli.Auth; +using Volo.Abp.Cli.Http; using Volo.Abp.Cli.ProjectBuilding.Building; using Volo.Abp.Cli.ProjectBuilding.Templates.App; using Volo.Abp.Cli.ProjectBuilding.Templates.Console; using Volo.Abp.Cli.ProjectBuilding.Templates.MvcModule; using Volo.Abp.Cli.ProjectBuilding.Templates.Wpf; using Volo.Abp.DependencyInjection; +using Volo.Abp.Threading; namespace Volo.Abp.Cli.ProjectBuilding { public class TemplateInfoProvider : ITemplateInfoProvider, ITransientDependency { - public TemplateInfo GetDefault() + public ILogger Logger { get; set; } + + public ICancellationTokenProvider CancellationTokenProvider { get; } + public IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; } + public AuthService AuthService { get; } + + public TemplateInfoProvider(ICancellationTokenProvider cancellationTokenProvider, + IRemoteServiceExceptionHandler remoteServiceExceptionHandler, + AuthService authService) { - return Get(AppTemplate.TemplateName); + CancellationTokenProvider = cancellationTokenProvider; + RemoteServiceExceptionHandler = remoteServiceExceptionHandler; + AuthService = authService; + + Logger = NullLogger.Instance; + } + + public async Task GetDefaultAsync() + { + var defaultTemplateName = await CheckProLicenseAsync() ? AppProTemplate.TemplateName : AppTemplate.TemplateName; + + return Get(defaultTemplateName); } public TemplateInfo Get(string name) @@ -35,5 +61,39 @@ namespace Volo.Abp.Cli.ProjectBuilding throw new Exception("There is no template found with given name: " + name); } } + + + private async Task CheckProLicenseAsync() + { + if (!AuthService.IsLoggedIn()) + { + return false; + } + + try + { + var url = $"{CliUrls.WwwAbpIo}api/license/check-user"; + + using (var client = new CliHttpClient()) + { + using (var response = await client.GetHttpResponseMessageWithRetryAsync(url, CancellationTokenProvider.Token, Logger)) + { + if (!response.IsSuccessStatusCode) + { + throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'"); + } + + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); + + var responseContent = await response.Content.ReadAsStringAsync(); + return JsonSerializer.Deserialize(responseContent); + } + } + } + catch (Exception) + { + return false; + } + } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs index 02b26eba39..cbbb094d11 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs @@ -49,7 +49,7 @@ namespace Volo.Abp.Cli.ProjectBuilding public async Task BuildAsync(ProjectBuildArgs args) { - var templateInfo = GetTemplateInfo(args); + var templateInfo = await GetTemplateInfoAsync(args); NormalizeArgs(args, templateInfo); @@ -175,11 +175,11 @@ namespace Volo.Abp.Cli.ProjectBuilding } } - private TemplateInfo GetTemplateInfo(ProjectBuildArgs args) + private async Task GetTemplateInfoAsync(ProjectBuildArgs args) { if (args.TemplateName.IsNullOrWhiteSpace()) { - return TemplateInfoProvider.GetDefault(); + return await TemplateInfoProvider.GetDefaultAsync(); } else { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs index 00a42491fe..a598d3483c 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs @@ -161,6 +161,11 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App { steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.HttpApi.HostWithIds")); steps.Add(new AngularEnvironmentFilePortChangeForSeparatedIdentityServersStep()); + + if (context.BuildArgs.MobileApp == MobileApp.ReactNative) + { + steps.Add(new ReactEnvironmentFilePortChangeForSeparatedIdentityServersStep()); + } } else { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/ReactEnvironmentFilePortChangeForSeparatedIdentityServersStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/ReactEnvironmentFilePortChangeForSeparatedIdentityServersStep.cs new file mode 100644 index 0000000000..66741f92c9 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/ReactEnvironmentFilePortChangeForSeparatedIdentityServersStep.cs @@ -0,0 +1,44 @@ +using System; +using System.Linq; +using Volo.Abp.Cli.ProjectBuilding.Building; + +namespace Volo.Abp.Cli.ProjectBuilding.Templates.App +{ + public class ReactEnvironmentFilePortChangeForSeparatedIdentityServersStep : ProjectBuildPipelineStep + { + public override void Execute(ProjectBuildContext context) + { + var fileEntry = context.Files.FirstOrDefault(x => + !x.IsDirectory && + x.Name.EndsWith($"{MobileApp.ReactNative.GetFolderName()}/Environment.js", + StringComparison.InvariantCultureIgnoreCase) + ); + + if (fileEntry == null) + { + return; + } + + fileEntry.NormalizeLineEndings(); + var lines = fileEntry.GetLines(); + + for (var i = 0; i < lines.Length; i++) + { + var line = lines[i]; + + if (line.Contains("issuer") && line.Contains("localhost")) + { + line = line.Replace("44305", "44301"); + } + else if (line.Contains("apiUrl") && line.Contains("localhost")) + { + line = line.Replace("44305", "44300"); + } + + lines[i] = line; + } + + fileEntry.SetLines(lines); + } + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs index 664ffd182b..ef8385d479 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs @@ -39,6 +39,11 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.Module "MyCompanyName.MyProjectName.Blazor" )); + steps.Add(new RemoveProjectFromSolutionStep( + "MyCompanyName.MyProjectName.Blazor.Host", + projectFolderPath: "/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host" + )); + steps.Add(new RemoveProjectFromSolutionStep( "MyCompanyName.MyProjectName.Web.Host", projectFolderPath: "/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host" diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs index c71e9591c0..d8571843fe 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs @@ -26,24 +26,20 @@ namespace Volo.Abp.Cli.ProjectModification private readonly PackageJsonFileFinder _packageJsonFileFinder; private readonly NpmGlobalPackagesChecker _npmGlobalPackagesChecker; - private readonly MyGetPackageListFinder _myGetPackageListFinder; private readonly Dictionary _fileVersionStorage = new Dictionary(); - private MyGetApiResponse _myGetApiResponse; public NpmPackagesUpdater( PackageJsonFileFinder packageJsonFileFinder, NpmGlobalPackagesChecker npmGlobalPackagesChecker, - MyGetPackageListFinder myGetPackageListFinder, ICancellationTokenProvider cancellationTokenProvider) { _packageJsonFileFinder = packageJsonFileFinder; _npmGlobalPackagesChecker = npmGlobalPackagesChecker; - _myGetPackageListFinder = myGetPackageListFinder; CancellationTokenProvider = cancellationTokenProvider; Logger = NullLogger.Instance; } - public async Task Update(string rootDirectory, bool includePreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false) + public async Task Update(string rootDirectory, bool includePreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false, string version = null) { var fileList = _packageJsonFileFinder.Find(rootDirectory); @@ -58,7 +54,7 @@ namespace Volo.Abp.Cli.ProjectModification async Task UpdateAsync(string file) { - var updated = await UpdatePackagesInFile(file, includePreviews,includeReleaseCandidates, switchToStable); + var updated = await UpdatePackagesInFile(file, includePreviews, includeReleaseCandidates, switchToStable, version); packagesUpdated.TryAdd(file, updated); } @@ -103,7 +99,7 @@ namespace Volo.Abp.Cli.ProjectModification private static async Task NpmrcFileExistAsync(string directoryName) { - return File.Exists(Path.Combine(directoryName, ".npmrc")); + return await Task.FromResult(File.Exists(Path.Combine(directoryName, ".npmrc"))); } private async Task CreateNpmrcFileAsync(string directoryName) @@ -157,18 +153,19 @@ namespace Volo.Abp.Cli.ProjectModification { using (var client = new CliHttpClient(TimeSpan.FromMinutes(1))) { - var response = await client.GetHttpResponseMessageWithRetryAsync( + using (var response = await client.GetHttpResponseMessageWithRetryAsync( url: $"{CliUrls.WwwAbpIo}api/myget/apikey/", cancellationToken: CancellationTokenProvider.Token, logger: Logger - ); - - return Encoding.Default.GetString(await response.Content.ReadAsByteArrayAsync()); + )) + { + return Encoding.Default.GetString(await response.Content.ReadAsByteArrayAsync()); + } } } catch (Exception) { - return ""; + return string.Empty; } } @@ -181,7 +178,8 @@ namespace Volo.Abp.Cli.ProjectModification string filePath, bool includePreviews = false, bool includeReleaseCandidates = false, - bool switchToStable = false) + bool switchToStable = false, + string specifiedVersion = null) { var packagesUpdated = false; var fileContent = File.ReadAllText(filePath); @@ -195,7 +193,7 @@ namespace Volo.Abp.Cli.ProjectModification foreach (var abpPackage in abpPackages) { - var updated = await TryUpdatingPackage(filePath, abpPackage, includePreviews, includeReleaseCandidates, switchToStable); + var updated = await TryUpdatingPackage(filePath, abpPackage, includePreviews, includeReleaseCandidates, switchToStable, specifiedVersion); if (updated) { @@ -215,27 +213,46 @@ namespace Volo.Abp.Cli.ProjectModification JProperty package, bool includePreviews = false, bool includeReleaseCandidates = false, - bool switchToStable = false) + bool switchToStable = false, + string specifiedVersion = null) { - var currentVersion = (string) package.Value; + var currentVersion = (string)package.Value; + + var version = string.Empty; - var version = ""; - if ((includePreviews || (!switchToStable && currentVersion.Contains("-preview"))) && !includeReleaseCandidates) + if (!specifiedVersion.IsNullOrWhiteSpace()) { - version = "preview"; + if (!SpecifiedVersionExists(specifiedVersion, package)) + { + return false; + } + + if (SemanticVersion.Parse(specifiedVersion) <= SemanticVersion.Parse(currentVersion.RemovePreFix("~", "^"))) + { + return false; + } + version = specifiedVersion.EnsureStartsWith('^'); } else { - if (!switchToStable && IsPrerelease(currentVersion)) + if ((includePreviews || (!switchToStable && (currentVersion != null && currentVersion.Contains("-preview")))) && !includeReleaseCandidates) { - version = await GetLatestVersion(package, true); + version = "preview"; } else { - version = await GetLatestVersion(package, includeReleaseCandidates); + if (!switchToStable && IsPrerelease(currentVersion)) + { + version = await GetLatestVersion(package, true); + } + else + { + version = await GetLatestVersion(package, includeReleaseCandidates); + } } } + if (string.IsNullOrEmpty(version) || version == currentVersion) { return false; @@ -258,18 +275,14 @@ namespace Volo.Abp.Cli.ProjectModification return version.Split("-", StringSplitOptions.RemoveEmptyEntries).Length > 1; } - protected virtual async Task GetLatestVersion( - JProperty package, - bool includeReleaseCandidates = false) + protected virtual async Task GetLatestVersion(JProperty package, bool includeReleaseCandidates = false) { if (_fileVersionStorage.ContainsKey(package.Name)) { - return _fileVersionStorage[package.Name]; + return await Task.FromResult(_fileVersionStorage[package.Name]); } - var versionListAsJson = CmdHelper.RunCmdAndGetOutput($"npm show {package.Name} versions"); - var versionList = JsonConvert.DeserializeObject(versionListAsJson) - .OrderByDescending(SemanticVersion.Parse, new VersionComparer()).ToList(); + var versionList = GetPackageVersionList(package); var newVersion = includeReleaseCandidates ? versionList.First() @@ -278,24 +291,24 @@ namespace Volo.Abp.Cli.ProjectModification if (string.IsNullOrEmpty(newVersion)) { _fileVersionStorage[package.Name] = newVersion; - return newVersion; + return await Task.FromResult(newVersion); } var newVersionWithPrefix = $"~{newVersion}"; _fileVersionStorage[package.Name] = newVersionWithPrefix; - return newVersionWithPrefix; + return await Task.FromResult(newVersionWithPrefix); } protected virtual List GetAbpPackagesFromPackageJson(JObject fileObject) { - var dependencyList = new[] {"dependencies", "devDependencies", "peerDependencies"}; + var dependencyList = new[] { "dependencies", "devDependencies", "peerDependencies" }; var abpPackages = new List(); foreach (var dependencyListName in dependencyList) { - var dependencies = (JObject) fileObject[dependencyListName]; + var dependencies = (JObject)fileObject[dependencyListName]; if (dependencies == null) { @@ -303,7 +316,9 @@ namespace Volo.Abp.Cli.ProjectModification } var properties = dependencies.Properties().ToList(); - abpPackages.AddRange(properties.Where(p => p.Name.StartsWith("@abp/") || p.Name.StartsWith("@volo/")) + + abpPackages + .AddRange(properties.Where(p => p.Name.StartsWith("@abp/") || p.Name.StartsWith("@volo/")) .ToList()); } @@ -327,5 +342,19 @@ namespace Volo.Abp.Cli.ProjectModification Logger.LogInformation($"Running npm install on {fileDirectory}"); CmdHelper.RunCmd($"cd {fileDirectory} && npm install"); } + + protected virtual List GetPackageVersionList(JProperty package) + { + var versionListAsJson = CmdHelper.RunCmdAndGetOutput($"npm show {package.Name} versions"); + return JsonConvert.DeserializeObject(versionListAsJson) + .OrderByDescending(SemanticVersion.Parse, new VersionComparer()).ToList(); + } + + protected virtual bool SpecifiedVersionExists(string version, JProperty package) + { + var versionList = GetPackageVersionList(package); + + return versionList.Any(v => v.Equals(version, StringComparison.OrdinalIgnoreCase)); + } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs index de25b11da7..ee736f3aa0 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs @@ -7,6 +7,8 @@ using System.Threading.Tasks; using System.Xml; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Cli.Args; +using Volo.Abp.Cli.Commands; using Volo.Abp.Cli.Http; using Volo.Abp.Cli.ProjectBuilding; using Volo.Abp.Cli.Utils; @@ -25,19 +27,22 @@ namespace Volo.Abp.Cli.ProjectModification protected DerivedClassFinder ModuleClassFinder { get; } protected ModuleClassDependcyAdder ModuleClassDependcyAdder { get; } protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; } + public BundleCommand BundleCommand { get; } public ProjectNugetPackageAdder( IJsonSerializer jsonSerializer, ProjectNpmPackageAdder npmPackageAdder, DerivedClassFinder moduleClassFinder, ModuleClassDependcyAdder moduleClassDependcyAdder, - IRemoteServiceExceptionHandler remoteServiceExceptionHandler) + IRemoteServiceExceptionHandler remoteServiceExceptionHandler, + BundleCommand bundleCommand) { JsonSerializer = jsonSerializer; NpmPackageAdder = npmPackageAdder; ModuleClassFinder = moduleClassFinder; ModuleClassDependcyAdder = moduleClassDependcyAdder; RemoteServiceExceptionHandler = remoteServiceExceptionHandler; + BundleCommand = bundleCommand; Logger = NullLogger.Instance; } @@ -50,14 +55,14 @@ namespace Volo.Abp.Cli.ProjectModification ); } - public Task AddAsync(string projectFile, NugetPackageInfo package, string version = null, + public async Task AddAsync(string projectFile, NugetPackageInfo package, string version = null, bool useDotnetCliToInstall = true) { var projectFileContent = File.ReadAllText(projectFile); if (projectFileContent.Contains($"\"{package.Name}\"")) { - return Task.CompletedTask; + return; } if (version == null) @@ -94,11 +99,14 @@ namespace Volo.Abp.Cli.ProjectModification } ModuleClassDependcyAdder.Add(moduleFiles.First(), package.ModuleClass); + } - Logger.LogInformation("Successfully installed."); + if (package.Target == NuGetPackageTarget.Blazor) + { + await RunBundleForBlazorAsync(projectFile); } - return Task.CompletedTask; + Logger.LogInformation("Successfully installed."); } private Task AddUsingDotnetCli(NugetPackageInfo package, string version = null) @@ -185,5 +193,15 @@ namespace Volo.Abp.Cli.ProjectModification return JsonSerializer.Deserialize(responseContent); } } + + protected virtual async Task RunBundleForBlazorAsync(string projectFile) + { + var args = new CommandLineArgs("bundle"); + + args.Options.Add(BundleCommand.Options.WorkingDirectory.Short, Path.GetDirectoryName(projectFile)); + args.Options.Add(BundleCommand.Options.ForceBuild.Short, string.Empty); + + await BundleCommand.ExecuteAsync(args); + } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs index 3bcdc34bc9..dc13511896 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Net; using System.Threading.Tasks; using Volo.Abp.Cli.Args; +using Volo.Abp.Cli.Bundling; using Volo.Abp.Cli.Commands; using Volo.Abp.Cli.Commands.Services; using Volo.Abp.Cli.Http; @@ -35,6 +36,7 @@ namespace Volo.Abp.Cli.ProjectModification public NugetPackageToLocalReferenceConverter NugetPackageToLocalReferenceConverter { get; } public AngularModuleSourceCodeAdder AngularModuleSourceCodeAdder { get; } public NewCommand NewCommand { get; } + public BundleCommand BundleCommand { get; } public SolutionModuleAdder( IJsonSerializer jsonSerializer, @@ -49,7 +51,8 @@ namespace Volo.Abp.Cli.ProjectModification SolutionFileModifier solutionFileModifier, NugetPackageToLocalReferenceConverter nugetPackageToLocalReferenceConverter, AngularModuleSourceCodeAdder angularModuleSourceCodeAdder, - NewCommand newCommand) + NewCommand newCommand, + BundleCommand bundleCommand) { JsonSerializer = jsonSerializer; ProjectNugetPackageAdder = projectNugetPackageAdder; @@ -64,6 +67,7 @@ namespace Volo.Abp.Cli.ProjectModification NugetPackageToLocalReferenceConverter = nugetPackageToLocalReferenceConverter; AngularModuleSourceCodeAdder = angularModuleSourceCodeAdder; NewCommand = newCommand; + BundleCommand = bundleCommand; Logger = NullLogger.Instance; } @@ -118,15 +122,33 @@ namespace Volo.Abp.Cli.ProjectModification await AddAngularPackages(solutionFile, module); } + await RunBundleForBlazorAsync(projectFiles, module); + ModifyDbContext(projectFiles, module, startupProject, skipDbMigrations); } + private async Task RunBundleForBlazorAsync(string[] projectFiles, ModuleWithMastersInfo module) + { + var blazorProject = projectFiles.FirstOrDefault(f => f.EndsWith(".Blazor.csproj")); + + if (blazorProject == null || !module.NugetPackages.Any(np=> np.Target == NuGetPackageTarget.Blazor)) + { + return; + } + + var args = new CommandLineArgs("bundle"); + + args.Options.Add(BundleCommand.Options.WorkingDirectory.Short, Path.GetDirectoryName(blazorProject)); + args.Options.Add(BundleCommand.Options.ForceBuild.Short, string.Empty); + + await BundleCommand.ExecuteAsync(args); + } + private async Task RemoveUnnecessaryProjectsAsync(string solutionDirectory, ModuleWithMastersInfo module, string[] projectFiles) { var moduleDirectory = Path.Combine(solutionDirectory, "modules", module.Name); - var moduleSolutionFile = - Directory.GetFiles(moduleDirectory, "*.sln", SearchOption.TopDirectoryOnly).First(); + var moduleSolutionFile = Directory.GetFiles(moduleDirectory, "*.sln", SearchOption.TopDirectoryOnly).First(); var isProjectTiered = await IsProjectTiered(projectFiles); if (!projectFiles.Any(p => p.EndsWith(".Blazor.csproj"))) @@ -149,6 +171,7 @@ namespace Volo.Abp.Cli.ProjectModification { await RemoveProjectByTarget(module, moduleSolutionFile, NuGetPackageTarget.EntityFrameworkCore, isProjectTiered); await RemoveProjectByPostFix(module, moduleSolutionFile, "test", ".EntityFrameworkCore.Tests"); + await ChangeDomainTestReferenceToMongoDB(module, moduleSolutionFile); } } @@ -163,6 +186,11 @@ namespace Volo.Abp.Cli.ProjectModification foreach (var package in packages) { + if (target == NuGetPackageTarget.Web && package.Name.StartsWith("Volo.Abp.Account")) + { + continue; + } + await SolutionFileModifier.RemoveProjectFromSolutionFileAsync(moduleSolutionFile, package.Name); var projectPath = Path.Combine(Path.GetDirectoryName(moduleSolutionFile), "src", package.Name); @@ -178,12 +206,27 @@ namespace Volo.Abp.Cli.ProjectModification { var srcPath = Path.Combine(Path.GetDirectoryName(moduleSolutionFile), targetFolder); var projectFolderPath = Directory.GetDirectories(srcPath).FirstOrDefault(d=> d.EndsWith(postFix)); - await SolutionFileModifier.RemoveProjectFromSolutionFileAsync(moduleSolutionFile, Path.GetDirectoryName(projectFolderPath)); + await SolutionFileModifier.RemoveProjectFromSolutionFileAsync(moduleSolutionFile, new DirectoryInfo(projectFolderPath).Name); if (Directory.Exists(projectFolderPath)) { Directory.Delete(projectFolderPath, true); } + + } + + private async Task ChangeDomainTestReferenceToMongoDB(ModuleWithMastersInfo module, string moduleSolutionFile) + { + var srcPath = Path.Combine(Path.GetDirectoryName(moduleSolutionFile), "test"); + var projectFolderPath = Directory.GetDirectories(srcPath).FirstOrDefault(d=> d.EndsWith("Domain.Tests")); + + var csprojFile = Directory.GetFiles(projectFolderPath).First(p => p.EndsWith(".csproj")); + var moduleFile = Directory.GetFiles(projectFolderPath).First(p => p.EndsWith("DomainTestModule.cs")); + + File.WriteAllText(csprojFile, File.ReadAllText(csprojFile).Replace("EntityFrameworkCore","MongoDB")); + File.WriteAllText(moduleFile, File.ReadAllText(moduleFile) + .Replace(".EntityFrameworkCore;",".MongoDB;") + .Replace("EntityFrameworkCoreTestModule","MongoDbTestModule")); } private async Task AddAngularPackages(string solutionFilePath, ModuleWithMastersInfo module) @@ -256,7 +299,9 @@ namespace Volo.Abp.Cli.ProjectModification ); } - await DeleteAppAndDemoFolderAsync(targetModuleFolder); + await DeleteRedundantHostProjects(targetModuleFolder,"app"); + await DeleteRedundantHostProjects(targetModuleFolder,"demo"); + await DeleteRedundantHostProjects(targetModuleFolder,"host"); if (module.MasterModuleInfos == null) { @@ -281,24 +326,22 @@ namespace Volo.Abp.Cli.ProjectModification await NewCommand.ExecuteAsync(args); } - private async Task DeleteAppAndDemoFolderAsync(string targetModuleFolder) + private async Task DeleteRedundantHostProjects(string targetModuleFolder, string folderName) { - var appFolder = Path.Combine(targetModuleFolder, "app"); - if (Directory.Exists(appFolder)) - { - Directory.Delete(appFolder, true); - } + var moduleSolutionFile = Directory.GetFiles(targetModuleFolder, "*.sln", SearchOption.TopDirectoryOnly).First(); - var demoFolder = Path.Combine(targetModuleFolder, "demo"); - if (Directory.Exists(demoFolder)) + var folder = Path.Combine(targetModuleFolder, folderName); + if (Directory.Exists(folder)) { - Directory.Delete(demoFolder, true); - } + var projects = Directory.GetDirectories(folder); - var hostFolder = Path.Combine(targetModuleFolder, "host"); - if (Directory.Exists(hostFolder)) - { - Directory.Delete(hostFolder, true); + foreach (var project in projects) + { + await SolutionFileModifier.RemoveProjectFromSolutionFileAsync(moduleSolutionFile, + new DirectoryInfo(project).Name); + } + + Directory.Delete(folder, true); } } @@ -444,73 +487,76 @@ namespace Volo.Abp.Cli.ProjectModification private async Task GetEmptyModuleProjectInfoAsync(string moduleName, bool newProTemplate = false) { - var module = new ModuleWithMastersInfo(); + var module = new ModuleWithMastersInfo + { + Name = moduleName, + DisplayName = moduleName, + MasterModuleInfos = new List() + }; - module.Name = moduleName; - module.DisplayName = moduleName; - module.EfCoreConfigureMethodName = $"{module.Name}.EntityFrameworkCore:Configure{module.Name}"; - module.MasterModuleInfos = new List(); + var moduleProjectName = module.Name.Split('.').Last(); + module.EfCoreConfigureMethodName = $"{module.Name}.EntityFrameworkCore:Configure{moduleProjectName}"; module.NugetPackages = new List { new NugetPackageInfo { Name = $"{module.Name}.Application", - ModuleClass = $"{module.Name}.{module.Name}ApplicationModule", + ModuleClass = $"{module.Name}.{moduleProjectName}ApplicationModule", Target = NuGetPackageTarget.Application }, new NugetPackageInfo { Name = $"{module.Name}.Application.Contracts", - ModuleClass = $"{module.Name}.{module.Name}ApplicationContractsModule", + ModuleClass = $"{module.Name}.{moduleProjectName}ApplicationContractsModule", Target = NuGetPackageTarget.ApplicationContracts }, new NugetPackageInfo { Name = $"{module.Name}.Blazor", - ModuleClass = $"{module.Name}.Blazor.{module.Name}BlazorModule", + ModuleClass = $"{module.Name}.Blazor.{moduleProjectName}BlazorModule", Target = NuGetPackageTarget.Blazor }, new NugetPackageInfo { Name = $"{module.Name}.Domain", - ModuleClass = $"{module.Name}.{module.Name}DomainModule", + ModuleClass = $"{module.Name}.{moduleProjectName}DomainModule", Target = NuGetPackageTarget.Domain }, new NugetPackageInfo { Name = $"{module.Name}.Domain.Shared", - ModuleClass = $"{module.Name}.{module.Name}DomainSharedModule", + ModuleClass = $"{module.Name}.{moduleProjectName}DomainSharedModule", Target = NuGetPackageTarget.DomainShared }, new NugetPackageInfo { Name = $"{module.Name}.EntityFrameworkCore", - ModuleClass = $"{module.Name}.EntityFrameworkCore.{module.Name}EntityFrameworkCoreModule", + ModuleClass = $"{module.Name}.EntityFrameworkCore.{moduleProjectName}EntityFrameworkCoreModule", Target = NuGetPackageTarget.EntityFrameworkCore }, new NugetPackageInfo { Name = $"{module.Name}.HttpApi", - ModuleClass = $"{module.Name}.{module.Name}HttpApiModule", + ModuleClass = $"{module.Name}.{moduleProjectName}HttpApiModule", Target = NuGetPackageTarget.HttpApi }, new NugetPackageInfo { Name = $"{module.Name}.HttpApi.Client", - ModuleClass = $"{module.Name}.{module.Name}HttpApiClientModule", + ModuleClass = $"{module.Name}.{moduleProjectName}HttpApiClientModule", Target = NuGetPackageTarget.HttpApiClient }, new NugetPackageInfo { Name = $"{module.Name}.MongoDB", - ModuleClass = $"{module.Name}.MongoDB.{module.Name}MongoDbModule", + ModuleClass = $"{module.Name}.MongoDB.{moduleProjectName}MongoDbModule", Target = NuGetPackageTarget.MongoDB }, new NugetPackageInfo { Name = $"{module.Name}.Web", - ModuleClass = $"{module.Name}.Web.{module.Name}WebModule", + ModuleClass = $"{module.Name}.Web.{moduleProjectName}WebModule", Target = NuGetPackageTarget.Web }, }; @@ -523,7 +569,9 @@ namespace Volo.Abp.Cli.ProjectModification protected virtual async Task IsProjectTiered(string[] projectFiles) { return projectFiles.Select(ProjectFileNameHelper.GetAssemblyNameFromProjectPath) - .Any(p => p.EndsWith(".IdentityServer") || p.EndsWith(".HttpApi.Host")); + .Any(p =>p.EndsWith(".HttpApi.Host")) + && projectFiles.Select(ProjectFileNameHelper.GetAssemblyNameFromProjectPath) + .Any(p => p.EndsWith(".IdentityServer")); } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs index 275bf23c76..c499dd0ee0 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs @@ -25,11 +25,11 @@ namespace Volo.Abp.Cli.ProjectModification Logger = NullLogger.Instance; } - public async Task UpdateSolutionAsync(string solutionPath, bool includePreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false, bool checkAll = false) + public async Task UpdateSolutionAsync(string solutionPath, bool includePreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false, bool checkAll = false, string version = null) { var projectPaths = ProjectFinder.GetProjectFiles(solutionPath); - if (checkAll) + if (checkAll && version.IsNullOrWhiteSpace()) { Task.WaitAll(projectPaths.Select(projectPath => UpdateInternalAsync(projectPath, includePreviews, includeReleaseCandidates, switchToStable)).ToArray()); } @@ -48,7 +48,8 @@ namespace Volo.Abp.Cli.ProjectModification switchToStable, latestVersionFromNuget, latestReleaseCandidateVersionFromNuget, - latestVersionFromMyGet); + latestVersionFromMyGet, + version); File.WriteAllText(filePath, updatedContent); } @@ -57,9 +58,9 @@ namespace Volo.Abp.Cli.ProjectModification } } - public async Task UpdateProjectAsync(string projectPath, bool includeNightlyPreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false, bool checkAll = false) + public async Task UpdateProjectAsync(string projectPath, bool includeNightlyPreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false, bool checkAll = false, string version = null) { - if (checkAll) + if (checkAll && version.IsNullOrWhiteSpace()) { await UpdateInternalAsync(projectPath, includeNightlyPreviews, includeReleaseCandidates, switchToStable); } @@ -77,7 +78,8 @@ namespace Volo.Abp.Cli.ProjectModification switchToStable, latestVersionFromNuget, latestReleaseCandidateVersionFromNuget, - latestVersionFromMyGet); + latestVersionFromMyGet, + version); File.WriteAllText(projectPath, updatedContent); } @@ -91,13 +93,26 @@ namespace Volo.Abp.Cli.ProjectModification File.WriteAllText(projectPath, updatedContent); } + protected virtual async Task SpecifiedVersionExists(string version, string packageId) + { + var versionList = await _nuGetService.GetPackageVersionListAsync(packageId); + + if (versionList.All(v => !v.Equals(version, StringComparison.OrdinalIgnoreCase))) + { + versionList = await _nuGetService.GetPackageVersionListAsync(packageId, true); + } + + return versionList.Any(v => v.Equals(version, StringComparison.OrdinalIgnoreCase)); + } + private async Task UpdateVoloPackagesAsync(string content, bool includeNightlyPreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false, SemanticVersion latestNugetVersion = null, SemanticVersion latestNugetReleaseCandidateVersion = null, - string latestMyGetVersion = null) + string latestMyGetVersion = null, + string specifiedVersion = null) { string packageId = null; @@ -129,40 +144,63 @@ namespace Volo.Abp.Cli.ProjectModification Logger.LogDebug("Checking package: \"{0}\" - Current version: {1}", packageId, currentSemanticVersion); - if ((includeNightlyPreviews || (currentVersion.Contains("-preview") && !switchToStable)) && !includeReleaseCandidates) + if (!specifiedVersion.IsNullOrWhiteSpace()) { - var latestVersion = latestMyGetVersion ?? await GetLatestVersionFromMyGet(packageId); - - if (currentVersion != latestVersion) + if (await SpecifiedVersionExists(specifiedVersion, packageId)) { - Logger.LogInformation("Updating package \"{0}\" from v{1} to v{2}.", packageId, currentVersion, latestVersion); - versionAttribute.Value = latestVersion; + var specifiedSemanticVersion = SemanticVersion.Parse(specifiedVersion); + if (specifiedSemanticVersion > currentSemanticVersion) + { + Logger.LogInformation("Updating package \"{0}\" from v{1} to v{2}.", packageId, currentVersion, specifiedVersion); + versionAttribute.Value = specifiedVersion; + } + else + { + Logger.LogWarning("Unable to update package \"{0}\" version v{1} to v{2}.", packageId, currentVersion, specifiedVersion); + } } else { - Logger.LogDebug("Package: \"{0}-v{1}\" is up to date.", packageId, currentVersion); + Logger.LogWarning("Package \"{0}\" specified version v{1} does not exist.", packageId, specifiedVersion); } } else { - SemanticVersion latestVersion; - if (currentSemanticVersion.IsPrerelease && !switchToStable) - { - latestVersion = latestNugetReleaseCandidateVersion ?? await _nuGetService.GetLatestVersionOrNullAsync(packageId, includeReleaseCandidates: true); - } - else - { - latestVersion = latestNugetVersion ?? await _nuGetService.GetLatestVersionOrNullAsync(packageId, includeReleaseCandidates: includeReleaseCandidates); - } - - if (latestVersion != null && (currentSemanticVersion < latestVersion || (currentSemanticVersion.IsPrerelease && switchToStable))) + if ((includeNightlyPreviews || (currentVersion.Contains("-preview") && !switchToStable)) && !includeReleaseCandidates) { - Logger.LogInformation("Updating package \"{0}\" from v{1} to v{2}.", packageId, currentSemanticVersion.ToString(), latestVersion.ToString()); - versionAttribute.Value = latestVersion.ToString(); + var latestVersion = latestMyGetVersion ?? await GetLatestVersionFromMyGet(packageId); + + if (currentVersion != latestVersion) + { + Logger.LogInformation("Updating package \"{0}\" from v{1} to v{2}.", packageId, currentVersion, latestVersion); + versionAttribute.Value = latestVersion; + } + else + { + Logger.LogDebug("Package: \"{0}-v{1}\" is up to date.", packageId, currentVersion); + } } else { - Logger.LogInformation("Package: \"{0}-v{1}\" is up to date.", packageId, currentSemanticVersion); + SemanticVersion latestVersion; + if (currentSemanticVersion.IsPrerelease && !switchToStable) + { + latestVersion = latestNugetReleaseCandidateVersion ?? await _nuGetService.GetLatestVersionOrNullAsync(packageId, includeReleaseCandidates: true); + } + else + { + latestVersion = latestNugetVersion ?? await _nuGetService.GetLatestVersionOrNullAsync(packageId, includeReleaseCandidates: includeReleaseCandidates); + } + + if (latestVersion != null && (currentSemanticVersion < latestVersion || (currentSemanticVersion.IsPrerelease && switchToStable))) + { + Logger.LogInformation("Updating package \"{0}\" from v{1} to v{2}.", packageId, currentSemanticVersion.ToString(), latestVersion.ToString()); + versionAttribute.Value = latestVersion.ToString(); + } + else + { + Logger.LogInformation("Package: \"{0}-v{1}\" is up to date.", packageId, currentSemanticVersion); + } } } } diff --git a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Program.cs b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Program.cs index c78d5f93f3..886520e95c 100644 --- a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Program.cs +++ b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Program.cs @@ -3,13 +3,13 @@ using Microsoft.Extensions.DependencyInjection; using Serilog; using Serilog.Events; using System.IO; -using Volo.Abp.Threading; +using System.Threading.Tasks; namespace Volo.Abp.Cli { public class Program { - private static void Main(string[] args) + private static async Task Main(string[] args) { Console.OutputEncoding = System.Text.Encoding.UTF8; @@ -37,11 +37,9 @@ namespace Volo.Abp.Cli { application.Initialize(); - AsyncHelper.RunSync( - () => application.ServiceProvider - .GetRequiredService() - .RunAsync(args) - ); + await application.ServiceProvider + .GetRequiredService() + .RunAsync(args); application.Shutdown(); } diff --git a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj index 887929dfa3..3926f8f298 100644 --- a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj +++ b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj @@ -26,10 +26,10 @@ - + - - - + + + diff --git a/framework/src/Volo.Abp.Dapper/Volo.Abp.Dapper.csproj b/framework/src/Volo.Abp.Dapper/Volo.Abp.Dapper.csproj index a2fd749d0e..0e267324af 100644 --- a/framework/src/Volo.Abp.Dapper/Volo.Abp.Dapper.csproj +++ b/framework/src/Volo.Abp.Dapper/Volo.Abp.Dapper.csproj @@ -19,7 +19,7 @@ - + diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Microsoft/EntityFrameworkCore/AbpOracleModelBuilderExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Microsoft/EntityFrameworkCore/AbpOracleModelBuilderExtensions.cs index 23943873c3..eaf6d94a83 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Microsoft/EntityFrameworkCore/AbpOracleModelBuilderExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Microsoft/EntityFrameworkCore/AbpOracleModelBuilderExtensions.cs @@ -1,13 +1,13 @@ -// using Volo.Abp.EntityFrameworkCore; -// -// namespace Microsoft.EntityFrameworkCore -// { -// public static class AbpOracleModelBuilderExtensions -// { -// public static void UseOracle( -// this ModelBuilder modelBuilder) -// { -// modelBuilder.SetDatabaseProvider(EfCoreDatabaseProvider.Oracle); -// } -// } -// } +using Volo.Abp.EntityFrameworkCore; + +namespace Microsoft.EntityFrameworkCore +{ + public static class AbpOracleModelBuilderExtensions + { + public static void UseOracle( + this ModelBuilder modelBuilder) + { + modelBuilder.SetDatabaseProvider(EfCoreDatabaseProvider.Oracle); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj index f42981a9ae..3d4e83e2ad 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj @@ -19,7 +19,7 @@ - + diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextOracleDevartExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextOracleDevartExtensions.cs index eaaed380af..43c4c178ee 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextOracleDevartExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextOracleDevartExtensions.cs @@ -1,27 +1,34 @@ -// using JetBrains.Annotations; -// using Microsoft.EntityFrameworkCore; -// using System; -// using Devart.Data.Oracle.Entity; -// using Volo.Abp.EntityFrameworkCore.DependencyInjection; -// -// namespace Volo.Abp.EntityFrameworkCore -// { -// public static class AbpDbContextConfigurationContextOracleDevartExtensions -// { -// public static DbContextOptionsBuilder UseOracle( -// [NotNull] this AbpDbContextConfigurationContext context, -// [CanBeNull] Action oracleOptionsAction = null, -// bool useExistingConnectionIfAvailable = false) -// { -// TODO: UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery); -// if (useExistingConnectionIfAvailable && context.ExistingConnection != null) -// { -// return context.DbContextOptions.UseOracle(context.ExistingConnection, oracleOptionsAction); -// } -// else -// { -// return context.DbContextOptions.UseOracle(context.ConnectionString, oracleOptionsAction); -// } -// } -// } -// } +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using System; +using Devart.Data.Oracle.Entity; +using Volo.Abp.EntityFrameworkCore.DependencyInjection; + +namespace Volo.Abp.EntityFrameworkCore +{ + public static class AbpDbContextConfigurationContextOracleDevartExtensions + { + public static DbContextOptionsBuilder UseOracle( + [NotNull] this AbpDbContextConfigurationContext context, + [CanBeNull] Action oracleOptionsAction = null, + bool useExistingConnectionIfAvailable = false) + { + if (useExistingConnectionIfAvailable && context.ExistingConnection != null) + { + return context.DbContextOptions.UseOracle(context.ExistingConnection, optionsBuilder => + { + optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery); + oracleOptionsAction?.Invoke(optionsBuilder); + }); + } + else + { + return context.DbContextOptions.UseOracle(context.ConnectionString, optionsBuilder => + { + optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery); + oracleOptionsAction?.Invoke(optionsBuilder); + }); + } + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/AbpDbContextOptionsOracleDevartExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/AbpDbContextOptionsOracleDevartExtensions.cs index 99cfc84b8e..20887ceb79 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/AbpDbContextOptionsOracleDevartExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/AbpDbContextOptionsOracleDevartExtensions.cs @@ -1,32 +1,32 @@ -// using JetBrains.Annotations; -// using System; -// using Devart.Data.Oracle.Entity; -// -// namespace Volo.Abp.EntityFrameworkCore -// { -// public static class AbpDbContextOptionsOracleDevartExtensions -// { -// public static void UseOracle( -// [NotNull] this AbpDbContextOptions options, -// [CanBeNull] Action oracleOptionsAction = null, -// bool useExistingConnectionIfAvailable = false) -// { -// options.Configure(context => -// { -// context.UseOracle(oracleOptionsAction, useExistingConnectionIfAvailable); -// }); -// } -// -// public static void UseOracle( -// [NotNull] this AbpDbContextOptions options, -// [CanBeNull] Action oracleOptionsAction = null, -// bool useExistingConnectionIfAvailable = false) -// where TDbContext : AbpDbContext -// { -// options.Configure(context => -// { -// context.UseOracle(oracleOptionsAction, useExistingConnectionIfAvailable); -// }); -// } -// } -// } +using JetBrains.Annotations; +using System; +using Devart.Data.Oracle.Entity; + +namespace Volo.Abp.EntityFrameworkCore +{ + public static class AbpDbContextOptionsOracleDevartExtensions + { + public static void UseOracle( + [NotNull] this AbpDbContextOptions options, + [CanBeNull] Action oracleOptionsAction = null, + bool useExistingConnectionIfAvailable = false) + { + options.Configure(context => + { + context.UseOracle(oracleOptionsAction, useExistingConnectionIfAvailable); + }); + } + + public static void UseOracle( + [NotNull] this AbpDbContextOptions options, + [CanBeNull] Action oracleOptionsAction = null, + bool useExistingConnectionIfAvailable = false) + where TDbContext : AbpDbContext + { + options.Configure(context => + { + context.UseOracle(oracleOptionsAction, useExistingConnectionIfAvailable); + }); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/Oracle/Devart/AbpEntityFrameworkCoreOracleDevartModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/Oracle/Devart/AbpEntityFrameworkCoreOracleDevartModule.cs index 3b1b9cc337..9580219cfc 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/Oracle/Devart/AbpEntityFrameworkCoreOracleDevartModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/Oracle/Devart/AbpEntityFrameworkCoreOracleDevartModule.cs @@ -1,22 +1,22 @@ -// using Volo.Abp.Guids; -// using Volo.Abp.Modularity; -// -// namespace Volo.Abp.EntityFrameworkCore.Oracle.Devart -// { -// [DependsOn( -// typeof(AbpEntityFrameworkCoreModule) -// )] -// public class AbpEntityFrameworkCoreOracleDevartModule : AbpModule -// { -// public override void ConfigureServices(ServiceConfigurationContext context) -// { -// Configure(options => -// { -// if (options.DefaultSequentialGuidType == null) -// { -// options.DefaultSequentialGuidType = SequentialGuidType.SequentialAsBinary; -// } -// }); -// } -// } -// } +using Volo.Abp.Guids; +using Volo.Abp.Modularity; + +namespace Volo.Abp.EntityFrameworkCore.Oracle.Devart +{ + [DependsOn( + typeof(AbpEntityFrameworkCoreModule) + )] + public class AbpEntityFrameworkCoreOracleDevartModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + if (options.DefaultSequentialGuidType == null) + { + options.DefaultSequentialGuidType = SequentialGuidType.SequentialAsBinary; + } + }); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj index 8e325342d4..8616838cc0 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj @@ -19,7 +19,7 @@ - + diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs index 6367bd24ff..eb8c4eb804 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs @@ -62,12 +62,6 @@ namespace Volo.Abp.AspNetCore.ExceptionHandling return CreateEntityNotFoundError(exception as EntityNotFoundException); } - if (exception is AbpAuthorizationException) - { - var authorizationException = exception as AbpAuthorizationException; - return new RemoteServiceErrorInfo(authorizationException.Message); - } - var errorInfo = new RemoteServiceErrorInfo(); if (exception is IUserFriendlyException) diff --git a/framework/src/Volo.Abp.Features/Volo.Abp.Features.csproj b/framework/src/Volo.Abp.Features/Volo.Abp.Features.csproj index a2d098f970..3bea3ea77f 100644 --- a/framework/src/Volo.Abp.Features/Volo.Abp.Features.csproj +++ b/framework/src/Volo.Abp.Features/Volo.Abp.Features.csproj @@ -15,7 +15,12 @@ - + + + + + + diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeatureErrorCodes.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeatureErrorCodes.cs new file mode 100644 index 0000000000..a5a4cf3a58 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeatureErrorCodes.cs @@ -0,0 +1,11 @@ +namespace Volo.Abp.Features +{ + public static class AbpFeatureErrorCodes + { + public const string FeatureIsNotEnabled = "Volo.Feature:010001"; + + public const string AllOfTheseFeaturesMustBeEnabled = "Volo.Feature:010002"; + + public const string AtLeastOneOfTheseFeaturesMustBeEnabled = "Volo.Feature:010003"; + } +} diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeaturesModule.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeaturesModule.cs index f30017feed..70c6e7f37d 100644 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeaturesModule.cs +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeaturesModule.cs @@ -1,15 +1,18 @@ using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; +using Volo.Abp.Features.Localization; using Volo.Abp.Localization; +using Volo.Abp.Localization.ExceptionHandling; using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; using Volo.Abp.Validation; +using Volo.Abp.VirtualFileSystem; namespace Volo.Abp.Features { [DependsOn( - typeof(AbpLocalizationAbstractionsModule), + typeof(AbpLocalizationModule), typeof(AbpMultiTenancyModule), typeof(AbpValidationModule) )] @@ -29,6 +32,23 @@ namespace Volo.Abp.Features options.ValueProviders.Add(); options.ValueProviders.Add(); }); + + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add("en") + .AddVirtualJson("/Volo/Abp/Features/Localization"); + }); + + Configure(options => + { + options.MapCodeNamespace("Volo.Feature", typeof(AbpFeatureResource)); + }); } private static void AutoAddDefinitionProviders(IServiceCollection services) diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureCheckerExtensions.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureCheckerExtensions.cs index 8850408df0..ba2b640031 100644 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureCheckerExtensions.cs +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureCheckerExtensions.cs @@ -9,8 +9,8 @@ namespace Volo.Abp.Features public static class FeatureCheckerExtensions { public static async Task GetAsync( - [NotNull] this IFeatureChecker featureChecker, - [NotNull] string name, + [NotNull] this IFeatureChecker featureChecker, + [NotNull] string name, T defaultValue = default) where T : struct { @@ -56,10 +56,11 @@ namespace Volo.Abp.Features { if (!(await featureChecker.IsEnabledAsync(featureName))) { - throw new AbpAuthorizationException("Feature is not enabled: " + featureName); + throw new AbpAuthorizationException(code: AbpFeatureErrorCodes.FeatureIsNotEnabled).WithData( + "FeatureName", featureName); } } - + public static async Task CheckEnabledAsync(this IFeatureChecker featureChecker, bool requiresAll, params string[] featureNames) { if (featureNames.IsNullOrEmpty()) @@ -73,10 +74,8 @@ namespace Volo.Abp.Features { if (!(await featureChecker.IsEnabledAsync(featureName))) { - throw new AbpAuthorizationException( - "Required features are not enabled. All of these features must be enabled: " + - string.Join(", ", featureNames) - ); + throw new AbpAuthorizationException(code: AbpFeatureErrorCodes.AllOfTheseFeaturesMustBeEnabled) + .WithData("FeatureNames", string.Join(", ", featureNames)); } } } @@ -90,11 +89,9 @@ namespace Volo.Abp.Features } } - throw new AbpAuthorizationException( - "Required features are not enabled. At least one of these features must be enabled: " + - string.Join(", ", featureNames) - ); + throw new AbpAuthorizationException(code: AbpFeatureErrorCodes.AtLeastOneOfTheseFeaturesMustBeEnabled) + .WithData("FeatureNames", string.Join(", ", featureNames)); } } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/AbpFeatureResource.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/AbpFeatureResource.cs new file mode 100644 index 0000000000..5871d550ad --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/AbpFeatureResource.cs @@ -0,0 +1,10 @@ +using Volo.Abp.Localization; + +namespace Volo.Abp.Features.Localization +{ + [LocalizationResourceName("AbpFeature")] + public class AbpFeatureResource + { + + } +} diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/en.json b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/en.json new file mode 100644 index 0000000000..de03dc11d0 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/en.json @@ -0,0 +1,8 @@ +{ + "culture": "en", + "texts": { + "Volo.Feature:010001": "Feature is not enabled: {FeatureName}", + "Volo.Feature:010002": "Required features are not enabled. All of these features must be enabled: {FeatureNames}", + "Volo.Feature:010003": "Required features are not enabled. At least one of these features must be enabled: {FeatureNames}" + } +} diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/tr.json b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/tr.json new file mode 100644 index 0000000000..4339c6ea71 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/tr.json @@ -0,0 +1,8 @@ +{ + "culture": "tr", + "texts": { + "Volo.Feature:010001": "Bu özellik etkin değil: {FeatureName}", + "Volo.Feature:010002": "Gerekli özellikler etkinleştirilmemiş. Bu özelliklerin tümü etkinleştirilmelidir: {FeatureNames}", + "Volo.Feature:010003": "Gerekli özellikler etkinleştirilmemiş. Bu özelliklerden en az birinin etkinleştirilmesi gerekir: {FeatureNames}" + } +} diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/zh-Hans.json b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/zh-Hans.json new file mode 100644 index 0000000000..4c6d99c281 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/zh-Hans.json @@ -0,0 +1,8 @@ +{ + "culture": "zh-Hans", + "texts": { + "Volo.Feature:010001": "功能未启用: {FeatureName}", + "Volo.Feature:010002": "必要的功能未启用. 这些功能需要启用: {FeatureNames}", + "Volo.Feature:010003": "必要的功能未启用. 需要启用这些功能中的一项:{FeatureNames}" + } +} diff --git a/framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj b/framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj index 68ce50ec9d..772774a77e 100644 --- a/framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj +++ b/framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentObjectValidationContributor.cs b/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentObjectValidationContributor.cs index e699e0093a..ccc290f354 100644 --- a/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentObjectValidationContributor.cs +++ b/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentObjectValidationContributor.cs @@ -26,7 +26,10 @@ namespace Volo.Abp.FluentValidation return; } - var result = validator.Validate(context.ValidatingObject); + var result = validator.Validate((IValidationContext) Activator.CreateInstance( + typeof(ValidationContext<>).MakeGenericType(context.ValidatingObject.GetType()), + context.ValidatingObject)); + if (!result.IsValid) { context.Errors.AddRange( diff --git a/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj b/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj index 3bd6638f67..4ec9d0a3b5 100644 --- a/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj +++ b/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj b/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj index 2000ca7ae4..9b1a1c9caf 100644 --- a/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj +++ b/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.Kafka/Volo.Abp.Kafka.csproj b/framework/src/Volo.Abp.Kafka/Volo.Abp.Kafka.csproj index 2a0b576f98..4f8a94fe8e 100644 --- a/framework/src/Volo.Abp.Kafka/Volo.Abp.Kafka.csproj +++ b/framework/src/Volo.Abp.Kafka/Volo.Abp.Kafka.csproj @@ -9,7 +9,7 @@ - + diff --git a/framework/src/Volo.Abp.MailKit/Volo.Abp.MailKit.csproj b/framework/src/Volo.Abp.MailKit/Volo.Abp.MailKit.csproj index ddded71dce..edc3752d47 100644 --- a/framework/src/Volo.Abp.MailKit/Volo.Abp.MailKit.csproj +++ b/framework/src/Volo.Abp.MailKit/Volo.Abp.MailKit.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.Minify/Volo.Abp.Minify.csproj b/framework/src/Volo.Abp.Minify/Volo.Abp.Minify.csproj index 1b2f266637..6f25c447f0 100644 --- a/framework/src/Volo.Abp.Minify/Volo.Abp.Minify.csproj +++ b/framework/src/Volo.Abp.Minify/Volo.Abp.Minify.csproj @@ -19,7 +19,7 @@ - + diff --git a/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj b/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj index e2f589b399..aa487ffc4e 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj +++ b/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.Quartz/Volo.Abp.Quartz.csproj b/framework/src/Volo.Abp.Quartz/Volo.Abp.Quartz.csproj index 198d2479e4..0fcc4da9f2 100644 --- a/framework/src/Volo.Abp.Quartz/Volo.Abp.Quartz.csproj +++ b/framework/src/Volo.Abp.Quartz/Volo.Abp.Quartz.csproj @@ -15,9 +15,9 @@ - - - + + + diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo.Abp.RabbitMQ.csproj b/framework/src/Volo.Abp.RabbitMQ/Volo.Abp.RabbitMQ.csproj index a21be8bdfa..abec7828ab 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo.Abp.RabbitMQ.csproj +++ b/framework/src/Volo.Abp.RabbitMQ/Volo.Abp.RabbitMQ.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqMessageConsumer.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqMessageConsumer.cs index 135156f7a8..fb1b0c7fe2 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqMessageConsumer.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqMessageConsumer.cs @@ -20,7 +20,7 @@ namespace Volo.Abp.RabbitMQ protected IExceptionNotifier ExceptionNotifier { get; } - protected AbpTimer Timer { get; } + protected AbpAsyncTimer Timer { get; } protected ExchangeDeclareConfiguration Exchange { get; private set; } @@ -38,7 +38,7 @@ namespace Volo.Abp.RabbitMQ public RabbitMqMessageConsumer( IConnectionPool connectionPool, - AbpTimer timer, + AbpAsyncTimer timer, IExceptionNotifier exceptionNotifier) { ConnectionPool = connectionPool; @@ -50,7 +50,7 @@ namespace Volo.Abp.RabbitMQ Callbacks = new ConcurrentBag>(); Timer.Period = 5000; //5 sec. - Timer.Elapsed += Timer_Elapsed; + Timer.Elapsed = Timer_Elapsed; Timer.RunOnStart = true; } @@ -77,7 +77,7 @@ namespace Volo.Abp.RabbitMQ await TrySendQueueBindCommandsAsync(); } - protected virtual void TrySendQueueBindCommands() + protected virtual async Task TrySendQueueBindCommandsAsync() { try { @@ -119,40 +119,33 @@ namespace Volo.Abp.RabbitMQ catch (Exception ex) { Logger.LogException(ex, LogLevel.Warning); - AsyncHelper.RunSync(() => ExceptionNotifier.NotifyAsync(ex, logLevel: LogLevel.Warning)); + await ExceptionNotifier.NotifyAsync(ex, logLevel: LogLevel.Warning); } } - protected virtual Task TrySendQueueBindCommandsAsync() - { - TrySendQueueBindCommands(); - return Task.CompletedTask; - } - public virtual void OnMessageReceived(Func callback) { Callbacks.Add(callback); } - protected virtual void Timer_Elapsed(object sender, EventArgs e) + protected virtual async Task Timer_Elapsed(AbpAsyncTimer timer) { if (Channel == null || Channel.IsOpen == false) { - TryCreateChannel(); - TrySendQueueBindCommands(); + await TryCreateChannelAsync(); + await TrySendQueueBindCommandsAsync(); } } - protected virtual void TryCreateChannel() + protected virtual async Task TryCreateChannelAsync() { - DisposeChannel(); + await DisposeChannelAsync(); try { var channel = ConnectionPool .Get(ConnectionName) .CreateModel(); - channel.ExchangeDeclare( exchange: Exchange.ExchangeName, type: Exchange.Type, @@ -172,7 +165,7 @@ namespace Volo.Abp.RabbitMQ var consumer = new EventingBasicConsumer(channel); consumer.Received += async (model, basicDeliverEventArgs) => { - await HandleIncomingMessage(channel, basicDeliverEventArgs); + await HandleIncomingMessageAsync(channel, basicDeliverEventArgs); }; channel.BasicConsume( @@ -186,11 +179,11 @@ namespace Volo.Abp.RabbitMQ catch (Exception ex) { Logger.LogException(ex, LogLevel.Warning); - AsyncHelper.RunSync(() => ExceptionNotifier.NotifyAsync(ex, logLevel: LogLevel.Warning)); + await ExceptionNotifier.NotifyAsync(ex, logLevel: LogLevel.Warning); } } - protected virtual async Task HandleIncomingMessage(IModel channel, BasicDeliverEventArgs basicDeliverEventArgs) + protected virtual async Task HandleIncomingMessageAsync(IModel channel, BasicDeliverEventArgs basicDeliverEventArgs) { try { @@ -208,6 +201,24 @@ namespace Volo.Abp.RabbitMQ } } + protected virtual async Task DisposeChannelAsync() + { + if (Channel == null) + { + return; + } + + try + { + Channel.Dispose(); + } + catch (Exception ex) + { + Logger.LogException(ex, LogLevel.Warning); + await ExceptionNotifier.NotifyAsync(ex, logLevel: LogLevel.Warning); + } + } + protected virtual void DisposeChannel() { if (Channel == null) diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Authorization/AbpAuthorizationException.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Authorization/AbpAuthorizationException.cs index ad5b0b65a3..c0a8c4d4f8 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Authorization/AbpAuthorizationException.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Authorization/AbpAuthorizationException.cs @@ -1,6 +1,7 @@ using System; using System.Runtime.Serialization; using Microsoft.Extensions.Logging; +using Volo.Abp.ExceptionHandling; using Volo.Abp.Logging; namespace Volo.Abp.Authorization @@ -9,7 +10,7 @@ namespace Volo.Abp.Authorization /// This exception is thrown on an unauthorized request. /// [Serializable] - public class AbpAuthorizationException : AbpException, IHasLogLevel + public class AbpAuthorizationException : AbpException, IHasLogLevel, IHasErrorCode { /// /// Severity of the exception. @@ -17,6 +18,11 @@ namespace Volo.Abp.Authorization /// public LogLevel LogLevel { get; set; } + /// + /// Error code. + /// + public string Code { get; } + /// /// Creates a new object. /// @@ -54,5 +60,24 @@ namespace Volo.Abp.Authorization { LogLevel = LogLevel.Warning; } + + /// + /// Creates a new object. + /// + /// Exception message + /// Exception code + /// Inner exception + public AbpAuthorizationException(string message = null, string code = null, Exception innerException = null) + : base(message, innerException) + { + Code = code; + LogLevel = LogLevel.Warning; + } + + public AbpAuthorizationException WithData(string name, object value) + { + Data[name] = value; + return this; + } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Swashbuckle/Volo.Abp.Swashbuckle.csproj b/framework/src/Volo.Abp.Swashbuckle/Volo.Abp.Swashbuckle.csproj index bbd09c5fed..e9d5e1afe5 100644 --- a/framework/src/Volo.Abp.Swashbuckle/Volo.Abp.Swashbuckle.csproj +++ b/framework/src/Volo.Abp.Swashbuckle/Volo.Abp.Swashbuckle.csproj @@ -2,7 +2,7 @@ - + netstandard2.0 Volo.Abp.Swashbuckle @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.TextTemplating/Volo.Abp.TextTemplating.csproj b/framework/src/Volo.Abp.TextTemplating/Volo.Abp.TextTemplating.csproj index 7885cefbaf..af14f9e42e 100644 --- a/framework/src/Volo.Abp.TextTemplating/Volo.Abp.TextTemplating.csproj +++ b/framework/src/Volo.Abp.TextTemplating/Volo.Abp.TextTemplating.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateLocalizer.cs b/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateLocalizer.cs index c3c67dd194..4e4a1e4833 100644 --- a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateLocalizer.cs +++ b/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateLocalizer.cs @@ -46,5 +46,20 @@ namespace Volo.Abp.TextTemplating var args = arguments.Skip(1).Where(x => x != null && !x.ToString().IsNullOrWhiteSpace()).ToArray(); return args.Any() ? _localizer[name.ToString(), args] : _localizer[name.ToString()]; } + + public int RequiredParameterCount => 1; + + public int ParameterCount => ScriptFunctionCall.MaximumParameterCount - 1; + + public ScriptVarParamKind VarParamKind => ScriptVarParamKind.Direct; + + public Type ReturnType => typeof(object); + + public ScriptParameterInfo GetParameterInfo(int index) + { + return index == 0 + ? new ScriptParameterInfo(typeof(string), "template_name") + : new ScriptParameterInfo(typeof(object), "value"); + } } } diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpAsyncTimer.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpAsyncTimer.cs new file mode 100644 index 0000000000..8ce369ef66 --- /dev/null +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpAsyncTimer.cs @@ -0,0 +1,127 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.DependencyInjection; +using Volo.Abp.ExceptionHandling; + +namespace Volo.Abp.Threading +{ + /// + /// A robust timer implementation that ensures no overlapping occurs. It waits exactly specified between ticks. + /// + public class AbpAsyncTimer : ITransientDependency + { + /// + /// This func is raised periodically according to Period of Timer. + /// + public Func Elapsed = _ => Task.CompletedTask; + + /// + /// Task period of timer (as milliseconds). + /// + public int Period { get; set; } + + /// + /// Indicates whether timer raises Elapsed event on Start method of Timer for once. + /// Default: False. + /// + public bool RunOnStart { get; set; } + + public ILogger Logger { get; set; } + + public IExceptionNotifier ExceptionNotifier { get; set; } + + private readonly Timer _taskTimer; + private volatile bool _performingTasks; + private volatile bool _isRunning; + + public AbpAsyncTimer() + { + ExceptionNotifier = NullExceptionNotifier.Instance; + Logger = NullLogger.Instance; + + _taskTimer = new Timer( + TimerCallBack, + null, + Timeout.Infinite, + Timeout.Infinite + ); + } + + public void Start(CancellationToken cancellationToken = default) + { + if (Period <= 0) + { + throw new AbpException("Period should be set before starting the timer!"); + } + + lock (_taskTimer) + { + _taskTimer.Change(RunOnStart ? 0 : Period, Timeout.Infinite); + _isRunning = true; + } + } + + public void Stop(CancellationToken cancellationToken = default) + { + lock (_taskTimer) + { + _taskTimer.Change(Timeout.Infinite, Timeout.Infinite); + while (_performingTasks) + { + Monitor.Wait(_taskTimer); + } + + _isRunning = false; + } + } + + /// + /// This method is called by _taskTimer. + /// + /// Not used argument + private void TimerCallBack(object state) + { + lock (_taskTimer) + { + if (!_isRunning || _performingTasks) + { + return; + } + + _taskTimer.Change(Timeout.Infinite, Timeout.Infinite); + _performingTasks = true; + } + + _ = Timer_Elapsed(); + } + + private async Task Timer_Elapsed() + { + try + { + await Elapsed(this); + } + catch(Exception ex) + { + Logger.LogException(ex); + await ExceptionNotifier.NotifyAsync(ex); + } + finally + { + lock (_taskTimer) + { + _performingTasks = false; + if (_isRunning) + { + _taskTimer.Change(Period, Timeout.Infinite); + } + + Monitor.Pulse(_taskTimer); + } + } + } + } +} diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpTimer.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpTimer.cs index 5c5041cdf6..e7e6efd5de 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpTimer.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpTimer.cs @@ -118,4 +118,4 @@ namespace Volo.Abp.Threading } } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Timing/Volo.Abp.Timing.csproj b/framework/src/Volo.Abp.Timing/Volo.Abp.Timing.csproj index 53ef23fd62..c0a9f0b271 100644 --- a/framework/src/Volo.Abp.Timing/Volo.Abp.Timing.csproj +++ b/framework/src/Volo.Abp.Timing/Volo.Abp.Timing.csproj @@ -26,7 +26,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj index c5bc024d75..7fa17a9fe7 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj @@ -9,7 +9,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo.csproj index 7c105c4de3..fb39407b4b 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo.Abp.AspNetCore.Serilog.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo.Abp.AspNetCore.Serilog.Tests.csproj index 432ece07dd..9c96018145 100644 --- a/framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo.Abp.AspNetCore.Serilog.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo.Abp.AspNetCore.Serilog.Tests.csproj @@ -10,7 +10,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo/Abp/AspNetCore/Serilog/Serilog_Enrichers_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo/Abp/AspNetCore/Serilog/Serilog_Enrichers_Tests.cs index 77de765f51..7bea930a37 100644 --- a/framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo/Abp/AspNetCore/Serilog/Serilog_Enrichers_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo/Abp/AspNetCore/Serilog/Serilog_Enrichers_Tests.cs @@ -88,10 +88,10 @@ namespace Volo.Abp.AspNetCore.Serilog executedLogEvent.ShouldNotBeNull(); executedLogEvent.Properties.ContainsKey(_serilogOptions.EnricherPropertyNames.CorrelationId) - .ShouldNotBeNull(); + .ShouldBeTrue(); ((ScalarValue) executedLogEvent.Properties[_serilogOptions.EnricherPropertyNames.CorrelationId]).Value .ShouldBe(result); } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.Authorization.Tests/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions_Tests.cs b/framework/test/Volo.Abp.Authorization.Tests/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions_Tests.cs new file mode 100644 index 0000000000..e8876aaebf --- /dev/null +++ b/framework/test/Volo.Abp.Authorization.Tests/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions_Tests.cs @@ -0,0 +1,49 @@ +using Shouldly; +using Volo.Abp.AspNetCore.ExceptionHandling; +using Volo.Abp.Authorization; +using Volo.Abp.Localization; +using Xunit; + +namespace Microsoft.AspNetCore.Authorization +{ + public class AbpAuthorizationServiceExtensions_Tests : AuthorizationTestBase + { + private readonly IExceptionToErrorInfoConverter _exceptionToErrorInfoConverter; + + public AbpAuthorizationServiceExtensions_Tests() + { + _exceptionToErrorInfoConverter = GetRequiredService(); + } + + [Fact] + public void Test_AbpAuthorizationException_Localization() + { + using (CultureHelper.Use("zh-Hans")) + { + var exception = new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenPolicyHasNotGranted); + var errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("授权失败! 提供的策略尚未授予."); + + exception = new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenPolicyHasNotGrantedWithPolicyName) + .WithData("PolicyName", "my_policy_name"); + errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("授权失败! 提供的策略尚未授予: my_policy_name"); + + exception = new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenPolicyHasNotGrantedForGivenResource) + .WithData("ResourceName", "my_resource_name"); + errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("授权失败! 提供的策略未授予提供的资源: my_resource_name"); + + exception = new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenRequirementHasNotGrantedForGivenResource) + .WithData("ResourceName", "my_resource_name"); + errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("授权失败! 提供的要求未授予提供的资源: my_resource_name"); + + exception = new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenRequirementsHasNotGrantedForGivenResource) + .WithData("ResourceName", "my_resource_name"); + errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("授权失败! 提供的要求未授予提供的资源: my_resource_name"); + } + } + } +} diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj b/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj index 165aaaa1d0..279523610e 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj @@ -12,6 +12,7 @@ + diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AbpAuthorizationTestModule.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AbpAuthorizationTestModule.cs index 492a36f8b9..69417e48c6 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AbpAuthorizationTestModule.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AbpAuthorizationTestModule.cs @@ -2,12 +2,14 @@ using Volo.Abp.Authorization.TestServices; using Volo.Abp.Autofac; using Volo.Abp.DynamicProxy; +using Volo.Abp.ExceptionHandling; using Volo.Abp.Modularity; namespace Volo.Abp.Authorization { [DependsOn(typeof(AbpAutofacModule))] [DependsOn(typeof(AbpAuthorizationModule))] + [DependsOn(typeof(AbpExceptionHandlingModule))] public class AbpAuthorizationTestModule : AbpModule { public override void PreConfigureServices(ServiceConfigurationContext context) @@ -22,4 +24,4 @@ namespace Volo.Abp.Authorization }); } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.BlobStoring.Aws.Tests/Volo/Abp/BlobStoring/Aws/AbpBlobStoringAwsTestModule.cs b/framework/test/Volo.Abp.BlobStoring.Aws.Tests/Volo/Abp/BlobStoring/Aws/AbpBlobStoringAwsTestModule.cs index d176a864e7..71a1cd8504 100644 --- a/framework/test/Volo.Abp.BlobStoring.Aws.Tests/Volo/Abp/BlobStoring/Aws/AbpBlobStoringAwsTestModule.cs +++ b/framework/test/Volo.Abp.BlobStoring.Aws.Tests/Volo/Abp/BlobStoring/Aws/AbpBlobStoringAwsTestModule.cs @@ -69,7 +69,7 @@ namespace Volo.Abp.BlobStoring.Aws private async Task DeleteBucketAsync(ApplicationShutdownContext context) { - var amazonS3Client = await context.ServiceProvider.GetService() + var amazonS3Client = await context.ServiceProvider.GetRequiredService() .GetAmazonS3Client(_configuration); if (await AmazonS3Util.DoesS3BucketExistV2Async(amazonS3Client, _randomContainerName)) @@ -89,4 +89,4 @@ namespace Volo.Abp.BlobStoring.Aws } } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj b/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj index 3edc355ca2..713b541431 100644 --- a/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj +++ b/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj @@ -9,6 +9,7 @@ + diff --git a/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/AbpFeaturesTestModule.cs b/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/AbpFeaturesTestModule.cs index 7b0927b80d..f5ff20e6f2 100644 --- a/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/AbpFeaturesTestModule.cs +++ b/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/AbpFeaturesTestModule.cs @@ -1,10 +1,12 @@ using Volo.Abp.Autofac; +using Volo.Abp.ExceptionHandling; using Volo.Abp.Modularity; namespace Volo.Abp.Features { [DependsOn( typeof(AbpFeaturesModule), + typeof(AbpExceptionHandlingModule), typeof(AbpTestBaseModule), typeof(AbpAutofacModule) )] @@ -12,7 +14,7 @@ namespace Volo.Abp.Features { public override void ConfigureServices(ServiceConfigurationContext context) { - + } } } diff --git a/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureCheckerExtensions_Tests.cs b/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureCheckerExtensions_Tests.cs new file mode 100644 index 0000000000..0df9548f3c --- /dev/null +++ b/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureCheckerExtensions_Tests.cs @@ -0,0 +1,40 @@ +using Shouldly; +using Volo.Abp.AspNetCore.ExceptionHandling; +using Volo.Abp.Authorization; +using Volo.Abp.Localization; +using Xunit; + +namespace Volo.Abp.Features +{ + public class FeatureCheckerExtensions_Tests : FeatureTestBase + { + private readonly IExceptionToErrorInfoConverter _exceptionToErrorInfoConverter; + + public FeatureCheckerExtensions_Tests() + { + _exceptionToErrorInfoConverter = GetRequiredService(); + } + + [Fact] + public void Test_AbpAuthorizationException_Localization() + { + using (CultureHelper.Use("zh-Hans")) + { + var exception = new AbpAuthorizationException(code: AbpFeatureErrorCodes.FeatureIsNotEnabled) + .WithData("FeatureName", "my_feature_name"); + var errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("功能未启用: my_feature_name"); + + exception = new AbpAuthorizationException(code: AbpFeatureErrorCodes.AllOfTheseFeaturesMustBeEnabled) + .WithData("FeatureNames", "my_feature_name, my_feature_name2"); + errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("必要的功能未启用. 这些功能需要启用: my_feature_name, my_feature_name2"); + + exception = new AbpAuthorizationException(code: AbpFeatureErrorCodes.AtLeastOneOfTheseFeaturesMustBeEnabled) + .WithData("FeatureNames", "my_feature_name, my_feature_name2"); + errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("必要的功能未启用. 需要启用这些功能中的一项:my_feature_name, my_feature_name2"); + } + } + } +} diff --git a/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo/Abp/VirtualFileSystem/VirtualFileProvider_Tests.cs b/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo/Abp/VirtualFileSystem/VirtualFileProvider_Tests.cs index aae01ff912..e453c5ee96 100644 --- a/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo/Abp/VirtualFileSystem/VirtualFileProvider_Tests.cs +++ b/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo/Abp/VirtualFileSystem/VirtualFileProvider_Tests.cs @@ -33,7 +33,7 @@ namespace Volo.Abp.VirtualFileSystem Encoding.UTF8.GetString(stream.GetAllBytes()).ShouldBe("//jquery-3-1-1-min.js-contents"); } } - + [Fact] public void Should_Define_And_Get_Embedded_Resources_With_Special_Chars() { @@ -57,10 +57,10 @@ namespace Volo.Abp.VirtualFileSystem var contents = _virtualFileProvider.GetDirectoryContents("/js"); //Assert - contents.Exists.ShouldNotBeNull(); + contents.Exists.ShouldBeTrue(); var contentList = contents.ToList(); - + contentList.ShouldContain(x => x.Name == "jquery-3-1-1-min.js"); contentList.ShouldContain(x => x.Name == "my{test}.2.9.min.js"); } @@ -74,7 +74,7 @@ namespace Volo.Abp.VirtualFileSystem var contents = _virtualFileProvider.GetDirectoryContents(path); //Assert - contents.Exists.ShouldNotBeNull(); + contents.Exists.ShouldBeTrue(); var contentList = contents.ToList(); contentList.ShouldContain(x => x.Name == "js"); diff --git a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Volo.Abp.Account.Web.IdentityServer.csproj b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Volo.Abp.Account.Web.IdentityServer.csproj index bcfd855190..91f9a3022e 100644 --- a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Volo.Abp.Account.Web.IdentityServer.csproj +++ b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Volo.Abp.Account.Web.IdentityServer.csproj @@ -34,7 +34,7 @@ - + diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj index c4ea6d9eb4..a38b454ba8 100644 --- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj @@ -6,7 +6,7 @@ - + diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Quartz/Volo.Abp.BackgroundJobs.DemoApp.Quartz.csproj b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Quartz/Volo.Abp.BackgroundJobs.DemoApp.Quartz.csproj index 0f5bd720a1..a9ac493329 100644 --- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Quartz/Volo.Abp.BackgroundJobs.DemoApp.Quartz.csproj +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Quartz/Volo.Abp.BackgroundJobs.DemoApp.Quartz.csproj @@ -6,7 +6,7 @@ - + diff --git a/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj b/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj index 3e11d85aee..41176d3edd 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj +++ b/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj @@ -15,9 +15,9 @@ - + - + diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo.Blogging.Application.csproj b/modules/blogging/src/Volo.Blogging.Application/Volo.Blogging.Application.csproj index 8c9f39e023..308a0b8c31 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo.Blogging.Application.csproj +++ b/modules/blogging/src/Volo.Blogging.Application/Volo.Blogging.Application.csproj @@ -11,7 +11,7 @@ - + diff --git a/modules/blogging/test/Volo.Blogging.Application.Tests/Volo/Blogging/PostAppService_Tests.cs b/modules/blogging/test/Volo.Blogging.Application.Tests/Volo/Blogging/PostAppService_Tests.cs index 260304d6ba..654ddcbe44 100644 --- a/modules/blogging/test/Volo.Blogging.Application.Tests/Volo/Blogging/PostAppService_Tests.cs +++ b/modules/blogging/test/Volo.Blogging.Application.Tests/Volo/Blogging/PostAppService_Tests.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using System.Threading.Tasks; using Shouldly; using Volo.Blogging.Blogs; @@ -55,7 +56,7 @@ namespace Volo.Blogging Url = title.Replace(" ", "-") }); - newPostDto.Id.ShouldNotBeNull(); + newPostDto.Id.ShouldNotBe(Guid.Empty); UsingDbContext(context => { @@ -87,7 +88,7 @@ namespace Volo.Blogging Content = newContent, Url = newTitle.Replace(" ", "-") }); - + UsingDbContext(context => { var post = context.Posts.FirstOrDefault(q => q.Id == oldPost.Id); diff --git a/modules/client-simulation/demo/Volo.ClientSimulation.Demo/Volo.ClientSimulation.Demo.csproj b/modules/client-simulation/demo/Volo.ClientSimulation.Demo/Volo.ClientSimulation.Demo.csproj index cc27807686..dbf58f3b71 100644 --- a/modules/client-simulation/demo/Volo.ClientSimulation.Demo/Volo.ClientSimulation.Demo.csproj +++ b/modules/client-simulation/demo/Volo.ClientSimulation.Demo/Volo.ClientSimulation.Demo.csproj @@ -9,7 +9,7 @@ - + diff --git a/modules/cms-kit/common.props b/modules/cms-kit/common.props deleted file mode 100644 index 420d9c492c..0000000000 --- a/modules/cms-kit/common.props +++ /dev/null @@ -1,13 +0,0 @@ - - - latest - 0.1.0 - $(NoWarn);CS1591;CS0436 - module - - - - - - - \ No newline at end of file diff --git a/modules/cms-kit/host/Volo.CmsKit.Host.Shared/Volo.CmsKit.Host.Shared.csproj b/modules/cms-kit/host/Volo.CmsKit.Host.Shared/Volo.CmsKit.Host.Shared.csproj index c6a4484865..aca54af174 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Host.Shared/Volo.CmsKit.Host.Shared.csproj +++ b/modules/cms-kit/host/Volo.CmsKit.Host.Shared/Volo.CmsKit.Host.Shared.csproj @@ -1,7 +1,5 @@ - - netstandard2.0 Volo.CmsKit diff --git a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Volo.CmsKit.HttpApi.Host.csproj b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Volo.CmsKit.HttpApi.Host.csproj index d019896648..688c47bc87 100644 --- a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Volo.CmsKit.HttpApi.Host.csproj +++ b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Volo.CmsKit.HttpApi.Host.csproj @@ -1,7 +1,5 @@ - - net5.0 Volo.CmsKit @@ -10,9 +8,9 @@ - + - + diff --git a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/Volo.CmsKit.IdentityServer.csproj b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/Volo.CmsKit.IdentityServer.csproj index fb149e574f..d70327c249 100644 --- a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/Volo.CmsKit.IdentityServer.csproj +++ b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/Volo.CmsKit.IdentityServer.csproj @@ -8,9 +8,9 @@ - + - + diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Host/Volo.CmsKit.Web.Host.csproj b/modules/cms-kit/host/Volo.CmsKit.Web.Host/Volo.CmsKit.Web.Host.csproj index 23a4b9fae3..266590c86b 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Host/Volo.CmsKit.Web.Host.csproj +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Host/Volo.CmsKit.Web.Host.csproj @@ -1,7 +1,5 @@ - - net5.0 Volo.CmsKit @@ -10,9 +8,9 @@ - + - + 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 483d54d9d5..2055266d20 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs @@ -18,6 +18,7 @@ using Volo.Abp.Autofac; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.SqlServer; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; using Volo.Abp.FeatureManagement; using Volo.Abp.Identity; using Volo.Abp.Identity.EntityFrameworkCore; @@ -56,6 +57,8 @@ namespace Volo.CmsKit typeof(AbpIdentityEntityFrameworkCoreModule), typeof(AbpPermissionManagementDomainIdentityModule), typeof(AbpFeatureManagementApplicationModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), + typeof(AbpFeatureManagementWebModule), typeof(AbpTenantManagementWebModule), typeof(AbpTenantManagementApplicationModule), typeof(AbpTenantManagementEntityFrameworkCoreModule), diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/EntityFrameworkCore/UnifiedDbContext.cs b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/EntityFrameworkCore/UnifiedDbContext.cs index 5eade47bd7..d1b31e0ae7 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/EntityFrameworkCore/UnifiedDbContext.cs +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/EntityFrameworkCore/UnifiedDbContext.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore; using Volo.Abp.AuditLogging.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; using Volo.Abp.Identity.EntityFrameworkCore; using Volo.Abp.PermissionManagement.EntityFrameworkCore; using Volo.Abp.SettingManagement.EntityFrameworkCore; @@ -25,6 +26,7 @@ namespace Volo.CmsKit.EntityFrameworkCore modelBuilder.ConfigureAuditLogging(); modelBuilder.ConfigureIdentity(); modelBuilder.ConfigureTenantManagement(); + modelBuilder.ConfigureFeatureManagement(); modelBuilder.ConfigureCmsKit(); } } diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201013061938_Initial.cs b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201013061938_Initial.cs deleted file mode 100644 index 73df34b298..0000000000 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201013061938_Initial.cs +++ /dev/null @@ -1,749 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Volo.CmsKit.Migrations -{ - public partial class Initial : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "AbpAuditLogs", - columns: table => new - { - Id = table.Column(nullable: false), - ExtraProperties = table.Column(nullable: true), - ConcurrencyStamp = table.Column(maxLength: 40, nullable: true), - ApplicationName = table.Column(maxLength: 96, nullable: true), - UserId = table.Column(nullable: true), - UserName = table.Column(maxLength: 256, nullable: true), - TenantId = table.Column(nullable: true), - TenantName = table.Column(nullable: true), - ImpersonatorUserId = table.Column(nullable: true), - ImpersonatorTenantId = table.Column(nullable: true), - ExecutionTime = table.Column(nullable: false), - ExecutionDuration = table.Column(nullable: false), - ClientIpAddress = table.Column(maxLength: 64, nullable: true), - ClientName = table.Column(maxLength: 128, nullable: true), - ClientId = table.Column(maxLength: 64, nullable: true), - CorrelationId = table.Column(maxLength: 64, nullable: true), - BrowserInfo = table.Column(maxLength: 512, nullable: true), - HttpMethod = table.Column(maxLength: 16, nullable: true), - Url = table.Column(maxLength: 256, nullable: true), - Exceptions = table.Column(maxLength: 4000, nullable: true), - Comments = table.Column(maxLength: 256, nullable: true), - HttpStatusCode = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpAuditLogs", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AbpClaimTypes", - columns: table => new - { - Id = table.Column(nullable: false), - ExtraProperties = table.Column(nullable: true), - ConcurrencyStamp = table.Column(maxLength: 40, nullable: true), - Name = table.Column(maxLength: 256, nullable: false), - Required = table.Column(nullable: false), - IsStatic = table.Column(nullable: false), - Regex = table.Column(maxLength: 512, nullable: true), - RegexDescription = table.Column(maxLength: 128, nullable: true), - Description = table.Column(maxLength: 256, nullable: true), - ValueType = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AbpOrganizationUnits", - columns: table => new - { - Id = table.Column(nullable: false), - ExtraProperties = table.Column(nullable: true), - ConcurrencyStamp = table.Column(maxLength: 40, nullable: true), - CreationTime = table.Column(nullable: false), - CreatorId = table.Column(nullable: true), - LastModificationTime = table.Column(nullable: true), - LastModifierId = table.Column(nullable: true), - IsDeleted = table.Column(nullable: false, defaultValue: false), - DeleterId = table.Column(nullable: true), - DeletionTime = table.Column(nullable: true), - TenantId = table.Column(nullable: true), - ParentId = table.Column(nullable: true), - Code = table.Column(maxLength: 95, nullable: false), - DisplayName = table.Column(maxLength: 128, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpOrganizationUnits", x => x.Id); - table.ForeignKey( - name: "FK_AbpOrganizationUnits_AbpOrganizationUnits_ParentId", - column: x => x.ParentId, - principalTable: "AbpOrganizationUnits", - principalColumn: "Id", - onDelete: ReferentialAction.Restrict); - }); - - migrationBuilder.CreateTable( - name: "AbpPermissionGrants", - columns: table => new - { - Id = table.Column(nullable: false), - TenantId = table.Column(nullable: true), - Name = table.Column(maxLength: 128, nullable: false), - ProviderName = table.Column(maxLength: 64, nullable: false), - ProviderKey = table.Column(maxLength: 64, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpPermissionGrants", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AbpRoles", - columns: table => new - { - Id = table.Column(nullable: false), - ExtraProperties = table.Column(nullable: true), - ConcurrencyStamp = table.Column(maxLength: 40, nullable: true), - TenantId = table.Column(nullable: true), - Name = table.Column(maxLength: 256, nullable: false), - NormalizedName = table.Column(maxLength: 256, nullable: false), - IsDefault = table.Column(nullable: false), - IsStatic = table.Column(nullable: false), - IsPublic = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpRoles", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AbpSettings", - columns: table => new - { - Id = table.Column(nullable: false), - Name = table.Column(maxLength: 128, nullable: false), - Value = table.Column(maxLength: 2048, nullable: false), - ProviderName = table.Column(maxLength: 64, nullable: true), - ProviderKey = table.Column(maxLength: 64, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpSettings", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AbpTenants", - columns: table => new - { - Id = table.Column(nullable: false), - ExtraProperties = table.Column(nullable: true), - ConcurrencyStamp = table.Column(maxLength: 40, nullable: true), - CreationTime = table.Column(nullable: false), - CreatorId = table.Column(nullable: true), - LastModificationTime = table.Column(nullable: true), - LastModifierId = table.Column(nullable: true), - IsDeleted = table.Column(nullable: false, defaultValue: false), - DeleterId = table.Column(nullable: true), - DeletionTime = table.Column(nullable: true), - Name = table.Column(maxLength: 64, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpTenants", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AbpUsers", - columns: table => new - { - Id = table.Column(nullable: false), - ExtraProperties = table.Column(nullable: true), - ConcurrencyStamp = table.Column(maxLength: 40, nullable: true), - CreationTime = table.Column(nullable: false), - CreatorId = table.Column(nullable: true), - LastModificationTime = table.Column(nullable: true), - LastModifierId = table.Column(nullable: true), - IsDeleted = table.Column(nullable: false, defaultValue: false), - DeleterId = table.Column(nullable: true), - DeletionTime = table.Column(nullable: true), - TenantId = table.Column(nullable: true), - UserName = table.Column(maxLength: 256, nullable: false), - NormalizedUserName = table.Column(maxLength: 256, nullable: false), - Name = table.Column(maxLength: 64, nullable: true), - Surname = table.Column(maxLength: 64, nullable: true), - Email = table.Column(maxLength: 256, nullable: false), - NormalizedEmail = table.Column(maxLength: 256, nullable: false), - EmailConfirmed = table.Column(nullable: false, defaultValue: false), - PasswordHash = table.Column(maxLength: 256, nullable: true), - SecurityStamp = table.Column(maxLength: 256, nullable: false), - PhoneNumber = table.Column(maxLength: 16, nullable: true), - PhoneNumberConfirmed = table.Column(nullable: false, defaultValue: false), - TwoFactorEnabled = table.Column(nullable: false, defaultValue: false), - LockoutEnd = table.Column(nullable: true), - LockoutEnabled = table.Column(nullable: false, defaultValue: false), - AccessFailedCount = table.Column(nullable: false, defaultValue: 0) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpUsers", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "CmsComments", - columns: table => new - { - Id = table.Column(nullable: false), - TenantId = table.Column(nullable: true), - EntityType = table.Column(maxLength: 64, nullable: false), - EntityId = table.Column(maxLength: 64, nullable: false), - Text = table.Column(maxLength: 512, nullable: false), - RepliedCommentId = table.Column(nullable: true), - CreatorId = table.Column(nullable: false), - CreationTime = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_CmsComments", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "CmsRatings", - columns: table => new - { - Id = table.Column(nullable: false), - TenantId = table.Column(nullable: true), - EntityType = table.Column(maxLength: 64, nullable: false), - EntityId = table.Column(maxLength: 64, nullable: false), - StarCount = table.Column(nullable: false), - CreatorId = table.Column(nullable: false), - CreationTime = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_CmsRatings", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "CmsUserReactions", - columns: table => new - { - Id = table.Column(nullable: false), - TenantId = table.Column(nullable: true), - EntityType = table.Column(maxLength: 64, nullable: false), - EntityId = table.Column(maxLength: 64, nullable: false), - ReactionName = table.Column(maxLength: 32, nullable: false), - CreatorId = table.Column(nullable: false), - CreationTime = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_CmsUserReactions", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "CmsUsers", - columns: table => new - { - Id = table.Column(nullable: false), - ExtraProperties = table.Column(nullable: true), - ConcurrencyStamp = table.Column(maxLength: 40, nullable: true), - TenantId = table.Column(nullable: true), - UserName = table.Column(maxLength: 256, nullable: false), - Email = table.Column(maxLength: 256, nullable: false), - Name = table.Column(maxLength: 64, nullable: true), - Surname = table.Column(maxLength: 64, nullable: true), - EmailConfirmed = table.Column(nullable: false, defaultValue: false), - PhoneNumber = table.Column(maxLength: 16, nullable: true), - PhoneNumberConfirmed = table.Column(nullable: false, defaultValue: false) - }, - constraints: table => - { - table.PrimaryKey("PK_CmsUsers", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AbpAuditLogActions", - columns: table => new - { - Id = table.Column(nullable: false), - TenantId = table.Column(nullable: true), - AuditLogId = table.Column(nullable: false), - ServiceName = table.Column(maxLength: 256, nullable: true), - MethodName = table.Column(maxLength: 128, nullable: true), - Parameters = table.Column(maxLength: 2000, nullable: true), - ExecutionTime = table.Column(nullable: false), - ExecutionDuration = table.Column(nullable: false), - ExtraProperties = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpAuditLogActions", x => x.Id); - table.ForeignKey( - name: "FK_AbpAuditLogActions_AbpAuditLogs_AuditLogId", - column: x => x.AuditLogId, - principalTable: "AbpAuditLogs", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AbpEntityChanges", - columns: table => new - { - Id = table.Column(nullable: false), - AuditLogId = table.Column(nullable: false), - TenantId = table.Column(nullable: true), - ChangeTime = table.Column(nullable: false), - ChangeType = table.Column(nullable: false), - EntityTenantId = table.Column(nullable: true), - EntityId = table.Column(maxLength: 128, nullable: false), - EntityTypeFullName = table.Column(maxLength: 128, nullable: false), - ExtraProperties = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpEntityChanges", x => x.Id); - table.ForeignKey( - name: "FK_AbpEntityChanges_AbpAuditLogs_AuditLogId", - column: x => x.AuditLogId, - principalTable: "AbpAuditLogs", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AbpOrganizationUnitRoles", - columns: table => new - { - RoleId = table.Column(nullable: false), - OrganizationUnitId = table.Column(nullable: false), - CreationTime = table.Column(nullable: false), - CreatorId = table.Column(nullable: true), - TenantId = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpOrganizationUnitRoles", x => new { x.OrganizationUnitId, x.RoleId }); - table.ForeignKey( - name: "FK_AbpOrganizationUnitRoles_AbpOrganizationUnits_OrganizationUnitId", - column: x => x.OrganizationUnitId, - principalTable: "AbpOrganizationUnits", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_AbpOrganizationUnitRoles_AbpRoles_RoleId", - column: x => x.RoleId, - principalTable: "AbpRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AbpRoleClaims", - columns: table => new - { - Id = table.Column(nullable: false), - TenantId = table.Column(nullable: true), - ClaimType = table.Column(maxLength: 256, nullable: false), - ClaimValue = table.Column(maxLength: 1024, nullable: true), - RoleId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpRoleClaims", x => x.Id); - table.ForeignKey( - name: "FK_AbpRoleClaims_AbpRoles_RoleId", - column: x => x.RoleId, - principalTable: "AbpRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AbpTenantConnectionStrings", - columns: table => new - { - TenantId = table.Column(nullable: false), - Name = table.Column(maxLength: 64, nullable: false), - Value = table.Column(maxLength: 1024, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpTenantConnectionStrings", x => new { x.TenantId, x.Name }); - table.ForeignKey( - name: "FK_AbpTenantConnectionStrings_AbpTenants_TenantId", - column: x => x.TenantId, - principalTable: "AbpTenants", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AbpUserClaims", - columns: table => new - { - Id = table.Column(nullable: false), - TenantId = table.Column(nullable: true), - ClaimType = table.Column(maxLength: 256, nullable: false), - ClaimValue = table.Column(maxLength: 1024, nullable: true), - UserId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpUserClaims", x => x.Id); - table.ForeignKey( - name: "FK_AbpUserClaims_AbpUsers_UserId", - column: x => x.UserId, - principalTable: "AbpUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AbpUserLogins", - columns: table => new - { - UserId = table.Column(nullable: false), - LoginProvider = table.Column(maxLength: 64, nullable: false), - TenantId = table.Column(nullable: true), - ProviderKey = table.Column(maxLength: 196, nullable: false), - ProviderDisplayName = table.Column(maxLength: 128, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpUserLogins", x => new { x.UserId, x.LoginProvider }); - table.ForeignKey( - name: "FK_AbpUserLogins_AbpUsers_UserId", - column: x => x.UserId, - principalTable: "AbpUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AbpUserOrganizationUnits", - columns: table => new - { - UserId = table.Column(nullable: false), - OrganizationUnitId = table.Column(nullable: false), - CreationTime = table.Column(nullable: false), - CreatorId = table.Column(nullable: true), - TenantId = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpUserOrganizationUnits", x => new { x.OrganizationUnitId, x.UserId }); - table.ForeignKey( - name: "FK_AbpUserOrganizationUnits_AbpOrganizationUnits_OrganizationUnitId", - column: x => x.OrganizationUnitId, - principalTable: "AbpOrganizationUnits", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_AbpUserOrganizationUnits_AbpUsers_UserId", - column: x => x.UserId, - principalTable: "AbpUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AbpUserRoles", - columns: table => new - { - UserId = table.Column(nullable: false), - RoleId = table.Column(nullable: false), - TenantId = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpUserRoles", x => new { x.UserId, x.RoleId }); - table.ForeignKey( - name: "FK_AbpUserRoles_AbpRoles_RoleId", - column: x => x.RoleId, - principalTable: "AbpRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_AbpUserRoles_AbpUsers_UserId", - column: x => x.UserId, - principalTable: "AbpUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AbpUserTokens", - columns: table => new - { - UserId = table.Column(nullable: false), - LoginProvider = table.Column(maxLength: 64, nullable: false), - Name = table.Column(maxLength: 128, nullable: false), - TenantId = table.Column(nullable: true), - Value = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); - table.ForeignKey( - name: "FK_AbpUserTokens_AbpUsers_UserId", - column: x => x.UserId, - principalTable: "AbpUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AbpEntityPropertyChanges", - columns: table => new - { - Id = table.Column(nullable: false), - TenantId = table.Column(nullable: true), - EntityChangeId = table.Column(nullable: false), - NewValue = table.Column(maxLength: 512, nullable: true), - OriginalValue = table.Column(maxLength: 512, nullable: true), - PropertyName = table.Column(maxLength: 128, nullable: false), - PropertyTypeFullName = table.Column(maxLength: 64, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpEntityPropertyChanges", x => x.Id); - table.ForeignKey( - name: "FK_AbpEntityPropertyChanges_AbpEntityChanges_EntityChangeId", - column: x => x.EntityChangeId, - principalTable: "AbpEntityChanges", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_AbpAuditLogActions_AuditLogId", - table: "AbpAuditLogActions", - column: "AuditLogId"); - - migrationBuilder.CreateIndex( - name: "IX_AbpAuditLogActions_TenantId_ServiceName_MethodName_ExecutionTime", - table: "AbpAuditLogActions", - columns: new[] { "TenantId", "ServiceName", "MethodName", "ExecutionTime" }); - - migrationBuilder.CreateIndex( - name: "IX_AbpAuditLogs_TenantId_ExecutionTime", - table: "AbpAuditLogs", - columns: new[] { "TenantId", "ExecutionTime" }); - - migrationBuilder.CreateIndex( - name: "IX_AbpAuditLogs_TenantId_UserId_ExecutionTime", - table: "AbpAuditLogs", - columns: new[] { "TenantId", "UserId", "ExecutionTime" }); - - migrationBuilder.CreateIndex( - name: "IX_AbpEntityChanges_AuditLogId", - table: "AbpEntityChanges", - column: "AuditLogId"); - - migrationBuilder.CreateIndex( - name: "IX_AbpEntityChanges_TenantId_EntityTypeFullName_EntityId", - table: "AbpEntityChanges", - columns: new[] { "TenantId", "EntityTypeFullName", "EntityId" }); - - migrationBuilder.CreateIndex( - name: "IX_AbpEntityPropertyChanges_EntityChangeId", - table: "AbpEntityPropertyChanges", - column: "EntityChangeId"); - - migrationBuilder.CreateIndex( - name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", - table: "AbpOrganizationUnitRoles", - columns: new[] { "RoleId", "OrganizationUnitId" }); - - migrationBuilder.CreateIndex( - name: "IX_AbpOrganizationUnits_Code", - table: "AbpOrganizationUnits", - column: "Code"); - - migrationBuilder.CreateIndex( - name: "IX_AbpOrganizationUnits_ParentId", - table: "AbpOrganizationUnits", - column: "ParentId"); - - migrationBuilder.CreateIndex( - name: "IX_AbpPermissionGrants_Name_ProviderName_ProviderKey", - table: "AbpPermissionGrants", - columns: new[] { "Name", "ProviderName", "ProviderKey" }); - - migrationBuilder.CreateIndex( - name: "IX_AbpRoleClaims_RoleId", - table: "AbpRoleClaims", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "IX_AbpRoles_NormalizedName", - table: "AbpRoles", - column: "NormalizedName"); - - migrationBuilder.CreateIndex( - name: "IX_AbpSettings_Name_ProviderName_ProviderKey", - table: "AbpSettings", - columns: new[] { "Name", "ProviderName", "ProviderKey" }); - - migrationBuilder.CreateIndex( - name: "IX_AbpTenants_Name", - table: "AbpTenants", - column: "Name"); - - migrationBuilder.CreateIndex( - name: "IX_AbpUserClaims_UserId", - table: "AbpUserClaims", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AbpUserLogins_LoginProvider_ProviderKey", - table: "AbpUserLogins", - columns: new[] { "LoginProvider", "ProviderKey" }); - - migrationBuilder.CreateIndex( - name: "IX_AbpUserOrganizationUnits_UserId_OrganizationUnitId", - table: "AbpUserOrganizationUnits", - columns: new[] { "UserId", "OrganizationUnitId" }); - - migrationBuilder.CreateIndex( - name: "IX_AbpUserRoles_RoleId_UserId", - table: "AbpUserRoles", - columns: new[] { "RoleId", "UserId" }); - - migrationBuilder.CreateIndex( - name: "IX_AbpUsers_Email", - table: "AbpUsers", - column: "Email"); - - migrationBuilder.CreateIndex( - name: "IX_AbpUsers_NormalizedEmail", - table: "AbpUsers", - column: "NormalizedEmail"); - - migrationBuilder.CreateIndex( - name: "IX_AbpUsers_NormalizedUserName", - table: "AbpUsers", - column: "NormalizedUserName"); - - migrationBuilder.CreateIndex( - name: "IX_AbpUsers_UserName", - table: "AbpUsers", - column: "UserName"); - - migrationBuilder.CreateIndex( - name: "IX_CmsComments_TenantId_RepliedCommentId", - table: "CmsComments", - columns: new[] { "TenantId", "RepliedCommentId" }); - - migrationBuilder.CreateIndex( - name: "IX_CmsComments_TenantId_EntityType_EntityId", - table: "CmsComments", - columns: new[] { "TenantId", "EntityType", "EntityId" }); - - migrationBuilder.CreateIndex( - name: "IX_CmsRatings_TenantId_EntityType_EntityId_CreatorId", - table: "CmsRatings", - columns: new[] { "TenantId", "EntityType", "EntityId", "CreatorId" }); - - migrationBuilder.CreateIndex( - name: "IX_CmsUserReactions_TenantId_EntityType_EntityId_ReactionName", - table: "CmsUserReactions", - columns: new[] { "TenantId", "EntityType", "EntityId", "ReactionName" }); - - migrationBuilder.CreateIndex( - name: "IX_CmsUserReactions_TenantId_CreatorId_EntityType_EntityId_ReactionName", - table: "CmsUserReactions", - columns: new[] { "TenantId", "CreatorId", "EntityType", "EntityId", "ReactionName" }); - - migrationBuilder.CreateIndex( - name: "IX_CmsUsers_TenantId_Email", - table: "CmsUsers", - columns: new[] { "TenantId", "Email" }); - - migrationBuilder.CreateIndex( - name: "IX_CmsUsers_TenantId_UserName", - table: "CmsUsers", - columns: new[] { "TenantId", "UserName" }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AbpAuditLogActions"); - - migrationBuilder.DropTable( - name: "AbpClaimTypes"); - - migrationBuilder.DropTable( - name: "AbpEntityPropertyChanges"); - - migrationBuilder.DropTable( - name: "AbpOrganizationUnitRoles"); - - migrationBuilder.DropTable( - name: "AbpPermissionGrants"); - - migrationBuilder.DropTable( - name: "AbpRoleClaims"); - - migrationBuilder.DropTable( - name: "AbpSettings"); - - migrationBuilder.DropTable( - name: "AbpTenantConnectionStrings"); - - migrationBuilder.DropTable( - name: "AbpUserClaims"); - - migrationBuilder.DropTable( - name: "AbpUserLogins"); - - migrationBuilder.DropTable( - name: "AbpUserOrganizationUnits"); - - migrationBuilder.DropTable( - name: "AbpUserRoles"); - - migrationBuilder.DropTable( - name: "AbpUserTokens"); - - migrationBuilder.DropTable( - name: "CmsComments"); - - migrationBuilder.DropTable( - name: "CmsRatings"); - - migrationBuilder.DropTable( - name: "CmsUserReactions"); - - migrationBuilder.DropTable( - name: "CmsUsers"); - - migrationBuilder.DropTable( - name: "AbpEntityChanges"); - - migrationBuilder.DropTable( - name: "AbpTenants"); - - migrationBuilder.DropTable( - name: "AbpOrganizationUnits"); - - migrationBuilder.DropTable( - name: "AbpRoles"); - - migrationBuilder.DropTable( - name: "AbpUsers"); - - migrationBuilder.DropTable( - name: "AbpAuditLogs"); - } - } -} diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201013061938_Initial.Designer.cs b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201210071514_Initial.Designer.cs similarity index 58% rename from modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201013061938_Initial.Designer.cs rename to modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201210071514_Initial.Designer.cs index 64e92cbea5..449f18fb53 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201013061938_Initial.Designer.cs +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201210071514_Initial.Designer.cs @@ -11,17 +11,17 @@ using Volo.CmsKit.EntityFrameworkCore; namespace Volo.CmsKit.Migrations { [DbContext(typeof(UnifiedDbContext))] - [Migration("20201013061938_Initial")] + [Migration("20201210071514_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder + .UseIdentityColumns() .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "3.1.8") .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasAnnotation("ProductVersion", "5.0.1"); modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => { @@ -30,99 +30,99 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("ApplicationName") - .HasColumnName("ApplicationName") + .HasMaxLength(96) .HasColumnType("nvarchar(96)") - .HasMaxLength(96); + .HasColumnName("ApplicationName"); b.Property("BrowserInfo") - .HasColumnName("BrowserInfo") + .HasMaxLength(512) .HasColumnType("nvarchar(512)") - .HasMaxLength(512); + .HasColumnName("BrowserInfo"); b.Property("ClientId") - .HasColumnName("ClientId") + .HasMaxLength(64) .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasColumnName("ClientId"); b.Property("ClientIpAddress") - .HasColumnName("ClientIpAddress") + .HasMaxLength(64) .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasColumnName("ClientIpAddress"); b.Property("ClientName") - .HasColumnName("ClientName") + .HasMaxLength(128) .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasColumnName("ClientName"); b.Property("Comments") - .HasColumnName("Comments") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("Comments"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp") + .HasMaxLength(40) .HasColumnType("nvarchar(40)") - .HasMaxLength(40); + .HasColumnName("ConcurrencyStamp"); b.Property("CorrelationId") - .HasColumnName("CorrelationId") + .HasMaxLength(64) .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasColumnName("CorrelationId"); b.Property("Exceptions") - .HasColumnName("Exceptions") + .HasMaxLength(4000) .HasColumnType("nvarchar(4000)") - .HasMaxLength(4000); + .HasColumnName("Exceptions"); b.Property("ExecutionDuration") - .HasColumnName("ExecutionDuration") - .HasColumnType("int"); + .HasColumnType("int") + .HasColumnName("ExecutionDuration"); b.Property("ExecutionTime") .HasColumnType("datetime2"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("HttpMethod") - .HasColumnName("HttpMethod") + .HasMaxLength(16) .HasColumnType("nvarchar(16)") - .HasMaxLength(16); + .HasColumnName("HttpMethod"); b.Property("HttpStatusCode") - .HasColumnName("HttpStatusCode") - .HasColumnType("int"); + .HasColumnType("int") + .HasColumnName("HttpStatusCode"); b.Property("ImpersonatorTenantId") - .HasColumnName("ImpersonatorTenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("ImpersonatorTenantId"); b.Property("ImpersonatorUserId") - .HasColumnName("ImpersonatorUserId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("ImpersonatorUserId"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.Property("TenantName") .HasColumnType("nvarchar(max)"); b.Property("Url") - .HasColumnName("Url") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("Url"); b.Property("UserId") - .HasColumnName("UserId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("UserId"); b.Property("UserName") - .HasColumnName("UserName") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("UserName"); b.HasKey("Id"); @@ -140,39 +140,39 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("AuditLogId") - .HasColumnName("AuditLogId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("AuditLogId"); b.Property("ExecutionDuration") - .HasColumnName("ExecutionDuration") - .HasColumnType("int"); + .HasColumnType("int") + .HasColumnName("ExecutionDuration"); b.Property("ExecutionTime") - .HasColumnName("ExecutionTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("ExecutionTime"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("MethodName") - .HasColumnName("MethodName") + .HasMaxLength(128) .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasColumnName("MethodName"); b.Property("Parameters") - .HasColumnName("Parameters") + .HasMaxLength(2000) .HasColumnType("nvarchar(2000)") - .HasMaxLength(2000); + .HasColumnName("Parameters"); b.Property("ServiceName") - .HasColumnName("ServiceName") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("ServiceName"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("Id"); @@ -190,39 +190,39 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("AuditLogId") - .HasColumnName("AuditLogId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("AuditLogId"); b.Property("ChangeTime") - .HasColumnName("ChangeTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("ChangeTime"); b.Property("ChangeType") - .HasColumnName("ChangeType") - .HasColumnType("tinyint"); + .HasColumnType("tinyint") + .HasColumnName("ChangeType"); b.Property("EntityId") .IsRequired() - .HasColumnName("EntityId") + .HasMaxLength(128) .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasColumnName("EntityId"); b.Property("EntityTenantId") .HasColumnType("uniqueidentifier"); b.Property("EntityTypeFullName") .IsRequired() - .HasColumnName("EntityTypeFullName") + .HasMaxLength(128) .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasColumnName("EntityTypeFullName"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("Id"); @@ -243,30 +243,30 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("NewValue") - .HasColumnName("NewValue") + .HasMaxLength(512) .HasColumnType("nvarchar(512)") - .HasMaxLength(512); + .HasColumnName("NewValue"); b.Property("OriginalValue") - .HasColumnName("OriginalValue") + .HasMaxLength(512) .HasColumnType("nvarchar(512)") - .HasMaxLength(512); + .HasColumnName("OriginalValue"); b.Property("PropertyName") .IsRequired() - .HasColumnName("PropertyName") + .HasMaxLength(128) .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasColumnName("PropertyName"); b.Property("PropertyTypeFullName") .IsRequired() - .HasColumnName("PropertyTypeFullName") + .HasMaxLength(64) .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasColumnName("PropertyTypeFullName"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("Id"); @@ -275,6 +275,37 @@ namespace Volo.CmsKit.Migrations b.ToTable("AbpEntityPropertyChanges"); }); + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpFeatureValues"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => { b.Property("Id") @@ -283,33 +314,33 @@ namespace Volo.CmsKit.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp") + .HasMaxLength(40) .HasColumnType("nvarchar(40)") - .HasMaxLength(40); + .HasColumnName("ConcurrencyStamp"); b.Property("Description") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("IsStatic") .HasColumnType("bit"); b.Property("Name") .IsRequired() - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("Regex") - .HasColumnType("nvarchar(512)") - .HasMaxLength(512); + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); b.Property("RegexDescription") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("Required") .HasColumnType("bit"); @@ -322,6 +353,33 @@ namespace Volo.CmsKit.Migrations b.ToTable("AbpClaimTypes"); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("SourceTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique() + .HasFilter("[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL"); + + b.ToTable("AbpLinkUsers"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => { b.Property("Id") @@ -330,39 +388,39 @@ namespace Volo.CmsKit.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp") + .HasMaxLength(40) .HasColumnType("nvarchar(40)") - .HasMaxLength(40); + .HasColumnName("ConcurrencyStamp"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("IsDefault") - .HasColumnName("IsDefault") - .HasColumnType("bit"); + .HasColumnType("bit") + .HasColumnName("IsDefault"); b.Property("IsPublic") - .HasColumnName("IsPublic") - .HasColumnType("bit"); + .HasColumnType("bit") + .HasColumnName("IsPublic"); b.Property("IsStatic") - .HasColumnName("IsStatic") - .HasColumnType("bit"); + .HasColumnType("bit") + .HasColumnName("IsStatic"); b.Property("Name") .IsRequired() - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("NormalizedName") .IsRequired() - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("Id"); @@ -378,19 +436,19 @@ namespace Volo.CmsKit.Migrations b.Property("ClaimType") .IsRequired() - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("ClaimValue") - .HasColumnType("nvarchar(1024)") - .HasMaxLength(1024); + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); b.Property("RoleId") .HasColumnType("uniqueidentifier"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("Id"); @@ -399,6 +457,81 @@ namespace Volo.CmsKit.Migrations b.ToTable("AbpRoleClaims"); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => { b.Property("Id") @@ -407,130 +540,136 @@ namespace Volo.CmsKit.Migrations b.Property("AccessFailedCount") .ValueGeneratedOnAdd() - .HasColumnName("AccessFailedCount") .HasColumnType("int") - .HasDefaultValue(0); + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp") + .HasMaxLength(40) .HasColumnType("nvarchar(40)") - .HasMaxLength(40); + .HasColumnName("ConcurrencyStamp"); b.Property("CreationTime") - .HasColumnName("CreationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); b.Property("CreatorId") - .HasColumnName("CreatorId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); b.Property("DeleterId") - .HasColumnName("DeleterId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); b.Property("DeletionTime") - .HasColumnName("DeletionTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); b.Property("Email") .IsRequired() - .HasColumnName("Email") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("Email"); b.Property("EmailConfirmed") .ValueGeneratedOnAdd() - .HasColumnName("EmailConfirmed") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("IsDeleted") .ValueGeneratedOnAdd() - .HasColumnName("IsDeleted") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); b.Property("LastModificationTime") - .HasColumnName("LastModificationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); b.Property("LastModifierId") - .HasColumnName("LastModifierId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); b.Property("LockoutEnabled") .ValueGeneratedOnAdd() - .HasColumnName("LockoutEnabled") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); b.Property("LockoutEnd") .HasColumnType("datetimeoffset"); b.Property("Name") - .HasColumnName("Name") + .HasMaxLength(64) .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasColumnName("Name"); b.Property("NormalizedEmail") .IsRequired() - .HasColumnName("NormalizedEmail") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("NormalizedEmail"); b.Property("NormalizedUserName") .IsRequired() - .HasColumnName("NormalizedUserName") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("NormalizedUserName"); b.Property("PasswordHash") - .HasColumnName("PasswordHash") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("PasswordHash"); b.Property("PhoneNumber") - .HasColumnName("PhoneNumber") + .HasMaxLength(16) .HasColumnType("nvarchar(16)") - .HasMaxLength(16); + .HasColumnName("PhoneNumber"); b.Property("PhoneNumberConfirmed") .ValueGeneratedOnAdd() - .HasColumnName("PhoneNumberConfirmed") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); b.Property("SecurityStamp") .IsRequired() - .HasColumnName("SecurityStamp") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("SecurityStamp"); b.Property("Surname") - .HasColumnName("Surname") + .HasMaxLength(64) .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasColumnName("Surname"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.Property("TwoFactorEnabled") .ValueGeneratedOnAdd() - .HasColumnName("TwoFactorEnabled") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); b.Property("UserName") .IsRequired() - .HasColumnName("UserName") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("UserName"); b.HasKey("Id"); @@ -552,16 +691,16 @@ namespace Volo.CmsKit.Migrations b.Property("ClaimType") .IsRequired() - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("ClaimValue") - .HasColumnType("nvarchar(1024)") - .HasMaxLength(1024); + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.Property("UserId") .HasColumnType("uniqueidentifier"); @@ -579,21 +718,21 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("LoginProvider") - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("ProviderKey") .IsRequired() - .HasColumnType("nvarchar(196)") - .HasMaxLength(196); + .HasMaxLength(196) + .HasColumnType("nvarchar(196)"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("UserId", "LoginProvider"); @@ -611,16 +750,16 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("CreationTime") - .HasColumnName("CreationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); b.Property("CreatorId") - .HasColumnName("CreatorId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("OrganizationUnitId", "UserId"); @@ -638,8 +777,8 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("UserId", "RoleId"); @@ -654,16 +793,16 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("LoginProvider") - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("Name") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.Property("Value") .HasColumnType("nvarchar(max)"); @@ -681,62 +820,62 @@ namespace Volo.CmsKit.Migrations b.Property("Code") .IsRequired() - .HasColumnName("Code") + .HasMaxLength(95) .HasColumnType("nvarchar(95)") - .HasMaxLength(95); + .HasColumnName("Code"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp") + .HasMaxLength(40) .HasColumnType("nvarchar(40)") - .HasMaxLength(40); + .HasColumnName("ConcurrencyStamp"); b.Property("CreationTime") - .HasColumnName("CreationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); b.Property("CreatorId") - .HasColumnName("CreatorId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); b.Property("DeleterId") - .HasColumnName("DeleterId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); b.Property("DeletionTime") - .HasColumnName("DeletionTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); b.Property("DisplayName") .IsRequired() - .HasColumnName("DisplayName") + .HasMaxLength(128) .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasColumnName("DisplayName"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("IsDeleted") .ValueGeneratedOnAdd() - .HasColumnName("IsDeleted") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); b.Property("LastModificationTime") - .HasColumnName("LastModificationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); b.Property("LastModifierId") - .HasColumnName("LastModifierId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); b.Property("ParentId") .HasColumnType("uniqueidentifier"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("Id"); @@ -756,16 +895,16 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("CreationTime") - .HasColumnName("CreationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); b.Property("CreatorId") - .HasColumnName("CreatorId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("OrganizationUnitId", "RoleId"); @@ -782,22 +921,22 @@ namespace Volo.CmsKit.Migrations b.Property("Name") .IsRequired() - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("ProviderKey") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("ProviderName") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("Id"); @@ -814,21 +953,21 @@ namespace Volo.CmsKit.Migrations b.Property("Name") .IsRequired() - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("ProviderKey") - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("ProviderName") - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("Value") .IsRequired() - .HasColumnType("nvarchar(2048)") - .HasMaxLength(2048); + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); b.HasKey("Id"); @@ -845,48 +984,48 @@ namespace Volo.CmsKit.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp") + .HasMaxLength(40) .HasColumnType("nvarchar(40)") - .HasMaxLength(40); + .HasColumnName("ConcurrencyStamp"); b.Property("CreationTime") - .HasColumnName("CreationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); b.Property("CreatorId") - .HasColumnName("CreatorId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); b.Property("DeleterId") - .HasColumnName("DeleterId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); b.Property("DeletionTime") - .HasColumnName("DeletionTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("IsDeleted") .ValueGeneratedOnAdd() - .HasColumnName("IsDeleted") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); b.Property("LastModificationTime") - .HasColumnName("LastModificationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); b.Property("LastModifierId") - .HasColumnName("LastModifierId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); b.Property("Name") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.HasKey("Id"); @@ -901,13 +1040,13 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("Name") - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("Value") .IsRequired() - .HasColumnType("nvarchar(1024)") - .HasMaxLength(1024); + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); b.HasKey("TenantId", "Name"); @@ -921,34 +1060,34 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("CreationTime") - .HasColumnName("CreationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); b.Property("CreatorId") - .HasColumnName("CreatorId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); b.Property("EntityId") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("EntityType") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("RepliedCommentId") .HasColumnType("uniqueidentifier"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.Property("Text") .IsRequired() - .HasColumnType("nvarchar(512)") - .HasMaxLength(512); + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); b.HasKey("Id"); @@ -966,22 +1105,22 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("CreationTime") - .HasColumnName("CreationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); b.Property("CreatorId") - .HasColumnName("CreatorId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); b.Property("EntityId") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("EntityType") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("StarCount") .HasColumnType("smallint"); @@ -1003,31 +1142,31 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("CreationTime") - .HasColumnName("CreationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); b.Property("CreatorId") - .HasColumnName("CreatorId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); b.Property("EntityId") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("EntityType") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("ReactionName") .IsRequired() - .HasColumnType("nvarchar(32)") - .HasMaxLength(32); + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("Id"); @@ -1046,56 +1185,56 @@ namespace Volo.CmsKit.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp") + .HasMaxLength(40) .HasColumnType("nvarchar(40)") - .HasMaxLength(40); + .HasColumnName("ConcurrencyStamp"); b.Property("Email") .IsRequired() - .HasColumnName("Email") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("Email"); b.Property("EmailConfirmed") .ValueGeneratedOnAdd() - .HasColumnName("EmailConfirmed") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("Name") - .HasColumnName("Name") + .HasMaxLength(64) .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasColumnName("Name"); b.Property("PhoneNumber") - .HasColumnName("PhoneNumber") + .HasMaxLength(16) .HasColumnType("nvarchar(16)") - .HasMaxLength(16); + .HasColumnName("PhoneNumber"); b.Property("PhoneNumberConfirmed") .ValueGeneratedOnAdd() - .HasColumnName("PhoneNumberConfirmed") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); b.Property("Surname") - .HasColumnName("Surname") + .HasMaxLength(64) .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasColumnName("Surname"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.Property("UserName") .IsRequired() - .HasColumnName("UserName") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("UserName"); b.HasKey("Id"); @@ -1229,6 +1368,46 @@ namespace Volo.CmsKit.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); #pragma warning restore 612, 618 } } diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201210071514_Initial.cs b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201210071514_Initial.cs new file mode 100644 index 0000000000..54f7ac975c --- /dev/null +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201210071514_Initial.cs @@ -0,0 +1,846 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Volo.CmsKit.Migrations +{ + public partial class Initial : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpAuditLogs", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ApplicationName = table.Column(type: "nvarchar(96)", maxLength: 96, nullable: true), + UserId = table.Column(type: "uniqueidentifier", nullable: true), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + TenantName = table.Column(type: "nvarchar(max)", nullable: true), + ImpersonatorUserId = table.Column(type: "uniqueidentifier", nullable: true), + ImpersonatorTenantId = table.Column(type: "uniqueidentifier", nullable: true), + ExecutionTime = table.Column(type: "datetime2", nullable: false), + ExecutionDuration = table.Column(type: "int", nullable: false), + ClientIpAddress = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + ClientName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), + ClientId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + CorrelationId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + BrowserInfo = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + HttpMethod = table.Column(type: "nvarchar(16)", maxLength: 16, nullable: true), + Url = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + Exceptions = table.Column(type: "nvarchar(4000)", maxLength: 4000, nullable: true), + Comments = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + HttpStatusCode = table.Column(type: "int", nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuditLogs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpClaimTypes", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Required = table.Column(type: "bit", nullable: false), + IsStatic = table.Column(type: "bit", nullable: false), + Regex = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + RegexDescription = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), + Description = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ValueType = table.Column(type: "int", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatureValues", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ProviderName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + ProviderKey = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureValues", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpLinkUsers", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + SourceUserId = table.Column(type: "uniqueidentifier", nullable: false), + SourceTenantId = table.Column(type: "uniqueidentifier", nullable: true), + TargetUserId = table.Column(type: "uniqueidentifier", nullable: false), + TargetTenantId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpLinkUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnits", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ParentId = table.Column(type: "uniqueidentifier", nullable: true), + Code = table.Column(type: "nvarchar(95)", maxLength: 95, nullable: false), + DisplayName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnits", x => x.Id); + table.ForeignKey( + name: "FK_AbpOrganizationUnits_AbpOrganizationUnits_ParentId", + column: x => x.ParentId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissionGrants", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ProviderName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + ProviderKey = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGrants", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpRoles", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + IsDefault = table.Column(type: "bit", nullable: false), + IsStatic = table.Column(type: "bit", nullable: false), + IsPublic = table.Column(type: "bit", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSecurityLogs", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ApplicationName = table.Column(type: "nvarchar(96)", maxLength: 96, nullable: true), + Identity = table.Column(type: "nvarchar(96)", maxLength: 96, nullable: true), + Action = table.Column(type: "nvarchar(96)", maxLength: 96, nullable: true), + UserId = table.Column(type: "uniqueidentifier", nullable: true), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + TenantName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + ClientId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + CorrelationId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + ClientIpAddress = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + BrowserInfo = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSecurityLogs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSettings", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "nvarchar(2048)", maxLength: 2048, nullable: false), + ProviderName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + ProviderKey = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSettings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpTenants", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTenants", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpUsers", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + Surname = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + EmailConfirmed = table.Column(type: "bit", nullable: false, defaultValue: false), + PasswordHash = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + SecurityStamp = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + IsExternal = table.Column(type: "bit", nullable: false, defaultValue: false), + PhoneNumber = table.Column(type: "nvarchar(16)", maxLength: 16, nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false, defaultValue: false), + TwoFactorEnabled = table.Column(type: "bit", nullable: false, defaultValue: false), + LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), + LockoutEnabled = table.Column(type: "bit", nullable: false, defaultValue: false), + AccessFailedCount = table.Column(type: "int", nullable: false, defaultValue: 0), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "CmsComments", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + EntityType = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + EntityId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + Text = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: false), + RepliedCommentId = table.Column(type: "uniqueidentifier", nullable: true), + CreatorId = table.Column(type: "uniqueidentifier", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CmsComments", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "CmsRatings", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + EntityType = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + EntityId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + StarCount = table.Column(type: "smallint", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CmsRatings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "CmsUserReactions", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + EntityType = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + EntityId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + ReactionName = table.Column(type: "nvarchar(32)", maxLength: 32, nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CmsUserReactions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "CmsUsers", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + Surname = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + EmailConfirmed = table.Column(type: "bit", nullable: false, defaultValue: false), + PhoneNumber = table.Column(type: "nvarchar(16)", maxLength: 16, nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false, defaultValue: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_CmsUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpAuditLogActions", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + AuditLogId = table.Column(type: "uniqueidentifier", nullable: false), + ServiceName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + MethodName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), + Parameters = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), + ExecutionTime = table.Column(type: "datetime2", nullable: false), + ExecutionDuration = table.Column(type: "int", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuditLogActions", x => x.Id); + table.ForeignKey( + name: "FK_AbpAuditLogActions_AbpAuditLogs_AuditLogId", + column: x => x.AuditLogId, + principalTable: "AbpAuditLogs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpEntityChanges", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + AuditLogId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ChangeTime = table.Column(type: "datetime2", nullable: false), + ChangeType = table.Column(type: "tinyint", nullable: false), + EntityTenantId = table.Column(type: "uniqueidentifier", nullable: true), + EntityId = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + EntityTypeFullName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEntityChanges", x => x.Id); + table.ForeignKey( + name: "FK_AbpEntityChanges_AbpAuditLogs_AuditLogId", + column: x => x.AuditLogId, + principalTable: "AbpAuditLogs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnitRoles", + columns: table => new + { + RoleId = table.Column(type: "uniqueidentifier", nullable: false), + OrganizationUnitId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnitRoles", x => new { x.OrganizationUnitId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpRoleClaims", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + RoleId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ClaimType = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + ClaimValue = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpRoleClaims_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpTenantConnectionStrings", + columns: table => new + { + TenantId = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + Value = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTenantConnectionStrings", x => new { x.TenantId, x.Name }); + table.ForeignKey( + name: "FK_AbpTenantConnectionStrings_AbpTenants_TenantId", + column: x => x.TenantId, + principalTable: "AbpTenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserClaims", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + UserId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ClaimType = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + ClaimValue = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpUserClaims_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserLogins", + columns: table => new + { + UserId = table.Column(type: "uniqueidentifier", nullable: false), + LoginProvider = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ProviderKey = table.Column(type: "nvarchar(196)", maxLength: 196, nullable: false), + ProviderDisplayName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserLogins", x => new { x.UserId, x.LoginProvider }); + table.ForeignKey( + name: "FK_AbpUserLogins_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserOrganizationUnits", + columns: table => new + { + UserId = table.Column(type: "uniqueidentifier", nullable: false), + OrganizationUnitId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserOrganizationUnits", x => new { x.OrganizationUnitId, x.UserId }); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserRoles", + columns: table => new + { + UserId = table.Column(type: "uniqueidentifier", nullable: false), + RoleId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserTokens", + columns: table => new + { + UserId = table.Column(type: "uniqueidentifier", nullable: false), + LoginProvider = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + Value = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AbpUserTokens_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpEntityPropertyChanges", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + EntityChangeId = table.Column(type: "uniqueidentifier", nullable: false), + NewValue = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + OriginalValue = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + PropertyName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + PropertyTypeFullName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEntityPropertyChanges", x => x.Id); + table.ForeignKey( + name: "FK_AbpEntityPropertyChanges_AbpEntityChanges_EntityChangeId", + column: x => x.EntityChangeId, + principalTable: "AbpEntityChanges", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogActions_AuditLogId", + table: "AbpAuditLogActions", + column: "AuditLogId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogActions_TenantId_ServiceName_MethodName_ExecutionTime", + table: "AbpAuditLogActions", + columns: new[] { "TenantId", "ServiceName", "MethodName", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogs_TenantId_ExecutionTime", + table: "AbpAuditLogs", + columns: new[] { "TenantId", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogs_TenantId_UserId_ExecutionTime", + table: "AbpAuditLogs", + columns: new[] { "TenantId", "UserId", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityChanges_AuditLogId", + table: "AbpEntityChanges", + column: "AuditLogId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityChanges_TenantId_EntityTypeFullName_EntityId", + table: "AbpEntityChanges", + columns: new[] { "TenantId", "EntityTypeFullName", "EntityId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityPropertyChanges_EntityChangeId", + table: "AbpEntityPropertyChanges", + column: "EntityChangeId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureValues_Name_ProviderName_ProviderKey", + table: "AbpFeatureValues", + columns: new[] { "Name", "ProviderName", "ProviderKey" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpLinkUsers_SourceUserId_SourceTenantId_TargetUserId_TargetTenantId", + table: "AbpLinkUsers", + columns: new[] { "SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId" }, + unique: true, + filter: "[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", + table: "AbpOrganizationUnitRoles", + columns: new[] { "RoleId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_Code", + table: "AbpOrganizationUnits", + column: "Code"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_ParentId", + table: "AbpOrganizationUnits", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGrants_Name_ProviderName_ProviderKey", + table: "AbpPermissionGrants", + columns: new[] { "Name", "ProviderName", "ProviderKey" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoleClaims_RoleId", + table: "AbpRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoles_NormalizedName", + table: "AbpRoles", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Action", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Action" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_ApplicationName", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "ApplicationName" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Identity", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Identity" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_UserId", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSettings_Name_ProviderName_ProviderKey", + table: "AbpSettings", + columns: new[] { "Name", "ProviderName", "ProviderKey" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_Name", + table: "AbpTenants", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserClaims_UserId", + table: "AbpUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserLogins_LoginProvider_ProviderKey", + table: "AbpUserLogins", + columns: new[] { "LoginProvider", "ProviderKey" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserOrganizationUnits_UserId_OrganizationUnitId", + table: "AbpUserOrganizationUnits", + columns: new[] { "UserId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserRoles_RoleId_UserId", + table: "AbpUserRoles", + columns: new[] { "RoleId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_Email", + table: "AbpUsers", + column: "Email"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedEmail", + table: "AbpUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedUserName", + table: "AbpUsers", + column: "NormalizedUserName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_UserName", + table: "AbpUsers", + column: "UserName"); + + migrationBuilder.CreateIndex( + name: "IX_CmsComments_TenantId_EntityType_EntityId", + table: "CmsComments", + columns: new[] { "TenantId", "EntityType", "EntityId" }); + + migrationBuilder.CreateIndex( + name: "IX_CmsComments_TenantId_RepliedCommentId", + table: "CmsComments", + columns: new[] { "TenantId", "RepliedCommentId" }); + + migrationBuilder.CreateIndex( + name: "IX_CmsRatings_TenantId_EntityType_EntityId_CreatorId", + table: "CmsRatings", + columns: new[] { "TenantId", "EntityType", "EntityId", "CreatorId" }); + + migrationBuilder.CreateIndex( + name: "IX_CmsUserReactions_TenantId_CreatorId_EntityType_EntityId_ReactionName", + table: "CmsUserReactions", + columns: new[] { "TenantId", "CreatorId", "EntityType", "EntityId", "ReactionName" }); + + migrationBuilder.CreateIndex( + name: "IX_CmsUserReactions_TenantId_EntityType_EntityId_ReactionName", + table: "CmsUserReactions", + columns: new[] { "TenantId", "EntityType", "EntityId", "ReactionName" }); + + migrationBuilder.CreateIndex( + name: "IX_CmsUsers_TenantId_Email", + table: "CmsUsers", + columns: new[] { "TenantId", "Email" }); + + migrationBuilder.CreateIndex( + name: "IX_CmsUsers_TenantId_UserName", + table: "CmsUsers", + columns: new[] { "TenantId", "UserName" }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpAuditLogActions"); + + migrationBuilder.DropTable( + name: "AbpClaimTypes"); + + migrationBuilder.DropTable( + name: "AbpEntityPropertyChanges"); + + migrationBuilder.DropTable( + name: "AbpFeatureValues"); + + migrationBuilder.DropTable( + name: "AbpLinkUsers"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnitRoles"); + + migrationBuilder.DropTable( + name: "AbpPermissionGrants"); + + migrationBuilder.DropTable( + name: "AbpRoleClaims"); + + migrationBuilder.DropTable( + name: "AbpSecurityLogs"); + + migrationBuilder.DropTable( + name: "AbpSettings"); + + migrationBuilder.DropTable( + name: "AbpTenantConnectionStrings"); + + migrationBuilder.DropTable( + name: "AbpUserClaims"); + + migrationBuilder.DropTable( + name: "AbpUserLogins"); + + migrationBuilder.DropTable( + name: "AbpUserOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpUserRoles"); + + migrationBuilder.DropTable( + name: "AbpUserTokens"); + + migrationBuilder.DropTable( + name: "CmsComments"); + + migrationBuilder.DropTable( + name: "CmsRatings"); + + migrationBuilder.DropTable( + name: "CmsUserReactions"); + + migrationBuilder.DropTable( + name: "CmsUsers"); + + migrationBuilder.DropTable( + name: "AbpEntityChanges"); + + migrationBuilder.DropTable( + name: "AbpTenants"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpRoles"); + + migrationBuilder.DropTable( + name: "AbpUsers"); + + migrationBuilder.DropTable( + name: "AbpAuditLogs"); + } + } +} diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs index 96721a1355..a082d0db17 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs @@ -16,10 +16,10 @@ namespace Volo.CmsKit.Migrations { #pragma warning disable 612, 618 modelBuilder + .UseIdentityColumns() .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "3.1.8") .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasAnnotation("ProductVersion", "5.0.1"); modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => { @@ -28,99 +28,99 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("ApplicationName") - .HasColumnName("ApplicationName") + .HasMaxLength(96) .HasColumnType("nvarchar(96)") - .HasMaxLength(96); + .HasColumnName("ApplicationName"); b.Property("BrowserInfo") - .HasColumnName("BrowserInfo") + .HasMaxLength(512) .HasColumnType("nvarchar(512)") - .HasMaxLength(512); + .HasColumnName("BrowserInfo"); b.Property("ClientId") - .HasColumnName("ClientId") + .HasMaxLength(64) .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasColumnName("ClientId"); b.Property("ClientIpAddress") - .HasColumnName("ClientIpAddress") + .HasMaxLength(64) .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasColumnName("ClientIpAddress"); b.Property("ClientName") - .HasColumnName("ClientName") + .HasMaxLength(128) .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasColumnName("ClientName"); b.Property("Comments") - .HasColumnName("Comments") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("Comments"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp") + .HasMaxLength(40) .HasColumnType("nvarchar(40)") - .HasMaxLength(40); + .HasColumnName("ConcurrencyStamp"); b.Property("CorrelationId") - .HasColumnName("CorrelationId") + .HasMaxLength(64) .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasColumnName("CorrelationId"); b.Property("Exceptions") - .HasColumnName("Exceptions") + .HasMaxLength(4000) .HasColumnType("nvarchar(4000)") - .HasMaxLength(4000); + .HasColumnName("Exceptions"); b.Property("ExecutionDuration") - .HasColumnName("ExecutionDuration") - .HasColumnType("int"); + .HasColumnType("int") + .HasColumnName("ExecutionDuration"); b.Property("ExecutionTime") .HasColumnType("datetime2"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("HttpMethod") - .HasColumnName("HttpMethod") + .HasMaxLength(16) .HasColumnType("nvarchar(16)") - .HasMaxLength(16); + .HasColumnName("HttpMethod"); b.Property("HttpStatusCode") - .HasColumnName("HttpStatusCode") - .HasColumnType("int"); + .HasColumnType("int") + .HasColumnName("HttpStatusCode"); b.Property("ImpersonatorTenantId") - .HasColumnName("ImpersonatorTenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("ImpersonatorTenantId"); b.Property("ImpersonatorUserId") - .HasColumnName("ImpersonatorUserId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("ImpersonatorUserId"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.Property("TenantName") .HasColumnType("nvarchar(max)"); b.Property("Url") - .HasColumnName("Url") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("Url"); b.Property("UserId") - .HasColumnName("UserId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("UserId"); b.Property("UserName") - .HasColumnName("UserName") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("UserName"); b.HasKey("Id"); @@ -138,39 +138,39 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("AuditLogId") - .HasColumnName("AuditLogId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("AuditLogId"); b.Property("ExecutionDuration") - .HasColumnName("ExecutionDuration") - .HasColumnType("int"); + .HasColumnType("int") + .HasColumnName("ExecutionDuration"); b.Property("ExecutionTime") - .HasColumnName("ExecutionTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("ExecutionTime"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("MethodName") - .HasColumnName("MethodName") + .HasMaxLength(128) .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasColumnName("MethodName"); b.Property("Parameters") - .HasColumnName("Parameters") + .HasMaxLength(2000) .HasColumnType("nvarchar(2000)") - .HasMaxLength(2000); + .HasColumnName("Parameters"); b.Property("ServiceName") - .HasColumnName("ServiceName") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("ServiceName"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("Id"); @@ -188,39 +188,39 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("AuditLogId") - .HasColumnName("AuditLogId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("AuditLogId"); b.Property("ChangeTime") - .HasColumnName("ChangeTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("ChangeTime"); b.Property("ChangeType") - .HasColumnName("ChangeType") - .HasColumnType("tinyint"); + .HasColumnType("tinyint") + .HasColumnName("ChangeType"); b.Property("EntityId") .IsRequired() - .HasColumnName("EntityId") + .HasMaxLength(128) .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasColumnName("EntityId"); b.Property("EntityTenantId") .HasColumnType("uniqueidentifier"); b.Property("EntityTypeFullName") .IsRequired() - .HasColumnName("EntityTypeFullName") + .HasMaxLength(128) .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasColumnName("EntityTypeFullName"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("Id"); @@ -241,30 +241,30 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("NewValue") - .HasColumnName("NewValue") + .HasMaxLength(512) .HasColumnType("nvarchar(512)") - .HasMaxLength(512); + .HasColumnName("NewValue"); b.Property("OriginalValue") - .HasColumnName("OriginalValue") + .HasMaxLength(512) .HasColumnType("nvarchar(512)") - .HasMaxLength(512); + .HasColumnName("OriginalValue"); b.Property("PropertyName") .IsRequired() - .HasColumnName("PropertyName") + .HasMaxLength(128) .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasColumnName("PropertyName"); b.Property("PropertyTypeFullName") .IsRequired() - .HasColumnName("PropertyTypeFullName") + .HasMaxLength(64) .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasColumnName("PropertyTypeFullName"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("Id"); @@ -273,6 +273,37 @@ namespace Volo.CmsKit.Migrations b.ToTable("AbpEntityPropertyChanges"); }); + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpFeatureValues"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => { b.Property("Id") @@ -281,33 +312,33 @@ namespace Volo.CmsKit.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp") + .HasMaxLength(40) .HasColumnType("nvarchar(40)") - .HasMaxLength(40); + .HasColumnName("ConcurrencyStamp"); b.Property("Description") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("IsStatic") .HasColumnType("bit"); b.Property("Name") .IsRequired() - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("Regex") - .HasColumnType("nvarchar(512)") - .HasMaxLength(512); + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); b.Property("RegexDescription") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("Required") .HasColumnType("bit"); @@ -320,6 +351,33 @@ namespace Volo.CmsKit.Migrations b.ToTable("AbpClaimTypes"); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("SourceTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique() + .HasFilter("[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL"); + + b.ToTable("AbpLinkUsers"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => { b.Property("Id") @@ -328,39 +386,39 @@ namespace Volo.CmsKit.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp") + .HasMaxLength(40) .HasColumnType("nvarchar(40)") - .HasMaxLength(40); + .HasColumnName("ConcurrencyStamp"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("IsDefault") - .HasColumnName("IsDefault") - .HasColumnType("bit"); + .HasColumnType("bit") + .HasColumnName("IsDefault"); b.Property("IsPublic") - .HasColumnName("IsPublic") - .HasColumnType("bit"); + .HasColumnType("bit") + .HasColumnName("IsPublic"); b.Property("IsStatic") - .HasColumnName("IsStatic") - .HasColumnType("bit"); + .HasColumnType("bit") + .HasColumnName("IsStatic"); b.Property("Name") .IsRequired() - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("NormalizedName") .IsRequired() - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("Id"); @@ -376,19 +434,19 @@ namespace Volo.CmsKit.Migrations b.Property("ClaimType") .IsRequired() - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("ClaimValue") - .HasColumnType("nvarchar(1024)") - .HasMaxLength(1024); + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); b.Property("RoleId") .HasColumnType("uniqueidentifier"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("Id"); @@ -397,6 +455,81 @@ namespace Volo.CmsKit.Migrations b.ToTable("AbpRoleClaims"); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => { b.Property("Id") @@ -405,130 +538,136 @@ namespace Volo.CmsKit.Migrations b.Property("AccessFailedCount") .ValueGeneratedOnAdd() - .HasColumnName("AccessFailedCount") .HasColumnType("int") - .HasDefaultValue(0); + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp") + .HasMaxLength(40) .HasColumnType("nvarchar(40)") - .HasMaxLength(40); + .HasColumnName("ConcurrencyStamp"); b.Property("CreationTime") - .HasColumnName("CreationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); b.Property("CreatorId") - .HasColumnName("CreatorId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); b.Property("DeleterId") - .HasColumnName("DeleterId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); b.Property("DeletionTime") - .HasColumnName("DeletionTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); b.Property("Email") .IsRequired() - .HasColumnName("Email") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("Email"); b.Property("EmailConfirmed") .ValueGeneratedOnAdd() - .HasColumnName("EmailConfirmed") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("IsDeleted") .ValueGeneratedOnAdd() - .HasColumnName("IsDeleted") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); b.Property("LastModificationTime") - .HasColumnName("LastModificationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); b.Property("LastModifierId") - .HasColumnName("LastModifierId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); b.Property("LockoutEnabled") .ValueGeneratedOnAdd() - .HasColumnName("LockoutEnabled") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); b.Property("LockoutEnd") .HasColumnType("datetimeoffset"); b.Property("Name") - .HasColumnName("Name") + .HasMaxLength(64) .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasColumnName("Name"); b.Property("NormalizedEmail") .IsRequired() - .HasColumnName("NormalizedEmail") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("NormalizedEmail"); b.Property("NormalizedUserName") .IsRequired() - .HasColumnName("NormalizedUserName") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("NormalizedUserName"); b.Property("PasswordHash") - .HasColumnName("PasswordHash") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("PasswordHash"); b.Property("PhoneNumber") - .HasColumnName("PhoneNumber") + .HasMaxLength(16) .HasColumnType("nvarchar(16)") - .HasMaxLength(16); + .HasColumnName("PhoneNumber"); b.Property("PhoneNumberConfirmed") .ValueGeneratedOnAdd() - .HasColumnName("PhoneNumberConfirmed") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); b.Property("SecurityStamp") .IsRequired() - .HasColumnName("SecurityStamp") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("SecurityStamp"); b.Property("Surname") - .HasColumnName("Surname") + .HasMaxLength(64) .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasColumnName("Surname"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.Property("TwoFactorEnabled") .ValueGeneratedOnAdd() - .HasColumnName("TwoFactorEnabled") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); b.Property("UserName") .IsRequired() - .HasColumnName("UserName") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("UserName"); b.HasKey("Id"); @@ -550,16 +689,16 @@ namespace Volo.CmsKit.Migrations b.Property("ClaimType") .IsRequired() - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("ClaimValue") - .HasColumnType("nvarchar(1024)") - .HasMaxLength(1024); + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.Property("UserId") .HasColumnType("uniqueidentifier"); @@ -577,21 +716,21 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("LoginProvider") - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("ProviderKey") .IsRequired() - .HasColumnType("nvarchar(196)") - .HasMaxLength(196); + .HasMaxLength(196) + .HasColumnType("nvarchar(196)"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("UserId", "LoginProvider"); @@ -609,16 +748,16 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("CreationTime") - .HasColumnName("CreationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); b.Property("CreatorId") - .HasColumnName("CreatorId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("OrganizationUnitId", "UserId"); @@ -636,8 +775,8 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("UserId", "RoleId"); @@ -652,16 +791,16 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("LoginProvider") - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("Name") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.Property("Value") .HasColumnType("nvarchar(max)"); @@ -679,62 +818,62 @@ namespace Volo.CmsKit.Migrations b.Property("Code") .IsRequired() - .HasColumnName("Code") + .HasMaxLength(95) .HasColumnType("nvarchar(95)") - .HasMaxLength(95); + .HasColumnName("Code"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp") + .HasMaxLength(40) .HasColumnType("nvarchar(40)") - .HasMaxLength(40); + .HasColumnName("ConcurrencyStamp"); b.Property("CreationTime") - .HasColumnName("CreationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); b.Property("CreatorId") - .HasColumnName("CreatorId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); b.Property("DeleterId") - .HasColumnName("DeleterId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); b.Property("DeletionTime") - .HasColumnName("DeletionTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); b.Property("DisplayName") .IsRequired() - .HasColumnName("DisplayName") + .HasMaxLength(128) .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasColumnName("DisplayName"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("IsDeleted") .ValueGeneratedOnAdd() - .HasColumnName("IsDeleted") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); b.Property("LastModificationTime") - .HasColumnName("LastModificationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); b.Property("LastModifierId") - .HasColumnName("LastModifierId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); b.Property("ParentId") .HasColumnType("uniqueidentifier"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("Id"); @@ -754,16 +893,16 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("CreationTime") - .HasColumnName("CreationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); b.Property("CreatorId") - .HasColumnName("CreatorId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("OrganizationUnitId", "RoleId"); @@ -780,22 +919,22 @@ namespace Volo.CmsKit.Migrations b.Property("Name") .IsRequired() - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("ProviderKey") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("ProviderName") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("Id"); @@ -812,21 +951,21 @@ namespace Volo.CmsKit.Migrations b.Property("Name") .IsRequired() - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("ProviderKey") - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("ProviderName") - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("Value") .IsRequired() - .HasColumnType("nvarchar(2048)") - .HasMaxLength(2048); + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); b.HasKey("Id"); @@ -843,48 +982,48 @@ namespace Volo.CmsKit.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp") + .HasMaxLength(40) .HasColumnType("nvarchar(40)") - .HasMaxLength(40); + .HasColumnName("ConcurrencyStamp"); b.Property("CreationTime") - .HasColumnName("CreationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); b.Property("CreatorId") - .HasColumnName("CreatorId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); b.Property("DeleterId") - .HasColumnName("DeleterId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); b.Property("DeletionTime") - .HasColumnName("DeletionTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("IsDeleted") .ValueGeneratedOnAdd() - .HasColumnName("IsDeleted") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); b.Property("LastModificationTime") - .HasColumnName("LastModificationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); b.Property("LastModifierId") - .HasColumnName("LastModifierId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); b.Property("Name") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.HasKey("Id"); @@ -899,13 +1038,13 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("Name") - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("Value") .IsRequired() - .HasColumnType("nvarchar(1024)") - .HasMaxLength(1024); + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); b.HasKey("TenantId", "Name"); @@ -919,34 +1058,34 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("CreationTime") - .HasColumnName("CreationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); b.Property("CreatorId") - .HasColumnName("CreatorId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); b.Property("EntityId") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("EntityType") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("RepliedCommentId") .HasColumnType("uniqueidentifier"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.Property("Text") .IsRequired() - .HasColumnType("nvarchar(512)") - .HasMaxLength(512); + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); b.HasKey("Id"); @@ -964,22 +1103,22 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("CreationTime") - .HasColumnName("CreationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); b.Property("CreatorId") - .HasColumnName("CreatorId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); b.Property("EntityId") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("EntityType") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("StarCount") .HasColumnType("smallint"); @@ -1001,31 +1140,31 @@ namespace Volo.CmsKit.Migrations .HasColumnType("uniqueidentifier"); b.Property("CreationTime") - .HasColumnName("CreationTime") - .HasColumnType("datetime2"); + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); b.Property("CreatorId") - .HasColumnName("CreatorId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); b.Property("EntityId") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("EntityType") .IsRequired() - .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); b.Property("ReactionName") .IsRequired() - .HasColumnType("nvarchar(32)") - .HasMaxLength(32); + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.HasKey("Id"); @@ -1044,56 +1183,56 @@ namespace Volo.CmsKit.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp") + .HasMaxLength(40) .HasColumnType("nvarchar(40)") - .HasMaxLength(40); + .HasColumnName("ConcurrencyStamp"); b.Property("Email") .IsRequired() - .HasColumnName("Email") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("Email"); b.Property("EmailConfirmed") .ValueGeneratedOnAdd() - .HasColumnName("EmailConfirmed") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties") - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); b.Property("Name") - .HasColumnName("Name") + .HasMaxLength(64) .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasColumnName("Name"); b.Property("PhoneNumber") - .HasColumnName("PhoneNumber") + .HasMaxLength(16) .HasColumnType("nvarchar(16)") - .HasMaxLength(16); + .HasColumnName("PhoneNumber"); b.Property("PhoneNumberConfirmed") .ValueGeneratedOnAdd() - .HasColumnName("PhoneNumberConfirmed") .HasColumnType("bit") - .HasDefaultValue(false); + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); b.Property("Surname") - .HasColumnName("Surname") + .HasMaxLength(64) .HasColumnType("nvarchar(64)") - .HasMaxLength(64); + .HasColumnName("Surname"); b.Property("TenantId") - .HasColumnName("TenantId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); b.Property("UserName") .IsRequired() - .HasColumnName("UserName") + .HasMaxLength(256) .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasColumnName("UserName"); b.HasKey("Id"); @@ -1227,6 +1366,46 @@ namespace Volo.CmsKit.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); #pragma warning restore 612, 618 } } diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Volo.CmsKit.Web.Unified.csproj b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Volo.CmsKit.Web.Unified.csproj index 70f6923cfc..152d740864 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Volo.CmsKit.Web.Unified.csproj +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Volo.CmsKit.Web.Unified.csproj @@ -1,7 +1,5 @@ - - net5.0 Volo.CmsKit @@ -10,9 +8,9 @@ - + - + diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/package.json b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/package.json index 78834de93d..f0bcbc6333 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/package.json +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/package.json @@ -3,6 +3,7 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "^4.0.0" + "@abp/aspnetcore.mvc.ui.theme.basic": "^4.0.0", + "@abp/star-rating-svg": "^4.0.0" } } \ No newline at end of file diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/star-rating-svg/css/star-rating-svg.css b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/star-rating-svg/css/star-rating-svg.css new file mode 100644 index 0000000000..2c0114687f --- /dev/null +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/star-rating-svg/css/star-rating-svg.css @@ -0,0 +1,37 @@ +.jq-stars { + display: inline-block; +} + +.jq-rating-label { + font-size: 22px; + display: inline-block; + position: relative; + vertical-align: top; + font-family: helvetica, arial, verdana; +} + +.jq-star { + width: 100px; + height: 100px; + display: inline-block; + cursor: pointer; +} + +.jq-star-svg { + width: 100%; + height: 100% ; +} + +.jq-star:hover .fs-star-svg polygon { +} + +.jq-star-svg polygon { + stroke: #000; + stroke-linejoin: round; +} + +/* un-used */ +.jq-shadow { + -webkit-filter: drop-shadow( -2px -2px 2px #888 ); + filter: drop-shadow( -2px -2px 2px #888 ); +} diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/star-rating-svg/js/jquery.star-rating-svg.min.js b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/star-rating-svg/js/jquery.star-rating-svg.min.js new file mode 100644 index 0000000000..df947cfe2b --- /dev/null +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/star-rating-svg/js/jquery.star-rating-svg.min.js @@ -0,0 +1 @@ +!function(a){"use strict";var b="starRating",c=function(){},d={totalStars:5,useFullStars:!1,emptyColor:"lightgray",hoverColor:"orange",activeColor:"gold",useGradient:!0,readOnly:!1,disableAfterRate:!0,starGradient:{start:"#FEF7CD",end:"#FF9511"},strokeWidth:0,strokeColor:"black",initialRating:0,starSize:40,callback:c,onHover:c,onLeave:c},e=function(c,e){var f;this.element=c,this.$el=a(c),this.settings=a.extend({},d,e),f=this.$el.data("rating")||this.settings.initialRating,this._state={rating:(Math.round(2*f)/2).toFixed(1)},this._uid=Math.floor(999*Math.random()),e.starGradient||this.settings.useGradient||(this.settings.starGradient.start=this.settings.starGradient.end=this.settings.activeColor),this._defaults=d,this._name=b,this.init()},f={init:function(){this.renderMarkup(),this.addListeners(),this.initRating()},addListeners:function(){this.settings.readOnly||(this.$stars.on("mouseover",this.hoverRating.bind(this)),this.$stars.on("mouseout",this.restoreState.bind(this)),this.$stars.on("click",this.handleRating.bind(this)))},hoverRating:function(a){var b=this.getIndex(a);this.paintStars(b,"hovered"),this.settings.onHover(b+1,this._state.rating,this.$el)},handleRating:function(a){var b=this.getIndex(a),c=b+1;this.applyRating(c,this.$el),this.executeCallback(c,this.$el),this.settings.disableAfterRate&&this.$stars.off()},applyRating:function(a){var b=a-1;this.paintStars(b,"active"),this._state.rating=b+1},restoreState:function(a){var b=this.getIndex(a),c=this._state.rating||-1;this.paintStars(c-1,"active"),this.settings.onLeave(b+1,this._state.rating,this.$el)},getIndex:function(b){var c=a(b.currentTarget),d=c.width(),e=a(b.target).attr("data-side");e=e?e:this.getOffsetByPixel(b,c,d),e=this.settings.useFullStars?"right":e;var f=c.index()-("left"===e?.5:0);return f=.5>f&&b.offsetX=d&&!this.settings.useFullStars?"left":"right"},initRating:function(){this.paintStars(this._state.rating-1,"active")},paintStars:function(b,c){var d,e,f,g;a.each(this.$stars,function(h,i){d=a(i).find('polygon[data-side="left"]'),e=a(i).find('polygon[data-side="right"]'),f=g=b>=h?c:"empty",f=h-b===.5?c:f,d.attr("class","svg-"+f+"-"+this._uid),e.attr("class","svg-"+g+"-"+this._uid)}.bind(this))},renderMarkup:function(){for(var a='
"+this.getLinearGradient(this._uid+"_SVGID_1_",this.settings.emptyColor,this.settings.emptyColor)+this.getLinearGradient(this._uid+"_SVGID_2_",this.settings.hoverColor,this.settings.hoverColor)+this.getLinearGradient(this._uid+"_SVGID_3_",this.settings.starGradient.start,this.settings.starGradient.end)+'
',b="",c=0;c '},executeCallback:function(a,b){var c=this.settings.callback;c(a,b)}},g={unload:function(){var c="plugin_"+b,d=a(this),e=d.data(c).$stars;e.off(),d.removeData(c).remove()},setRating:function(c,d){var e="plugin_"+b,f=a(this),g=f.data(e);c>g.settings.totalStars||0>c||(d&&(c=Math.round(c)),g.applyRating(c))},getRating:function(){var c="plugin_"+b,d=a(this),e=d.data(c);return e._state.rating}};a.extend(e.prototype,f),a.fn[b]=function(c){if(!a.isPlainObject(c)){if(g.hasOwnProperty(c))return g[c].apply(this,Array.prototype.slice.call(arguments,1));a.error("Method "+c+" does not exist on "+b+".js")}return this.each(function(){a.data(this,"plugin_"+b)||a.data(this,"plugin_"+b,new e(this,c))})}}(jQuery,window,document); \ No newline at end of file diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/yarn.lock b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/yarn.lock index bc2ae6b5df..709cd49e05 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/yarn.lock +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/yarn.lock @@ -154,6 +154,14 @@ "@abp/core" "~4.0.0" select2 "^4.0.13" +"@abp/star-rating-svg@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@abp/star-rating-svg/-/star-rating-svg-4.0.0.tgz#cc39ead00ef49dd342e3236290eb36fc6976b016" + integrity sha512-+b9QwYl1Ayo1BFAqINhWlhVDQxCrv0yPHtqTMpaPVQSLvsO92HX9fGAaZlC5Cu+uesmlBiNWchTBXeqEccQh5g== + dependencies: + "@abp/jquery" "~4.0.0" + star-rating-svg "^3.5.0" + "@abp/sweetalert@~4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@abp/sweetalert/-/sweetalert-4.0.0.tgz#0d93e92e95c6855aef7e19532a7513a078ece216" @@ -2321,6 +2329,11 @@ stack-trace@0.0.10: resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= +star-rating-svg@^3.5.0: + version "3.5.0" + resolved "https://registry.npmjs.org/star-rating-svg/-/star-rating-svg-3.5.0.tgz#72b147015a433da63153fb607af6d51c7c1ea364" + integrity sha1-crFHAVpDPaYxU/tgevbVHHweo2Q= + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js index b853a9c186..1c08e38538 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js @@ -121,6 +121,11 @@ $form.submit(function (e) { e.preventDefault(); var formAsObject = $form.serializeFormToObject(); + + if (formAsObject.repliedCommentId == ''){ + formAsObject.repliedCommentId = null; + } + volo.cmsKit.public.comments.commentPublic.create( $commentArea.attr('data-entity-type'), $commentArea.attr('data-entity-id'), diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Volo.CmsKit.Application.Tests.csproj b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Volo.CmsKit.Application.Tests.csproj index 9093a9e11c..26c4be533f 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Volo.CmsKit.Application.Tests.csproj +++ b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Volo.CmsKit.Application.Tests.csproj @@ -1,7 +1,5 @@ - - net5.0 Volo.CmsKit diff --git a/modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Volo.CmsKit.Domain.Tests.csproj b/modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Volo.CmsKit.Domain.Tests.csproj index 405fa79568..d80255ba61 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Volo.CmsKit.Domain.Tests.csproj +++ b/modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Volo.CmsKit.Domain.Tests.csproj @@ -1,7 +1,5 @@ - - net5.0 Volo.CmsKit diff --git a/modules/cms-kit/test/Volo.CmsKit.EntityFrameworkCore.Tests/Volo.CmsKit.EntityFrameworkCore.Tests.csproj b/modules/cms-kit/test/Volo.CmsKit.EntityFrameworkCore.Tests/Volo.CmsKit.EntityFrameworkCore.Tests.csproj index e639191049..b7033afe20 100644 --- a/modules/cms-kit/test/Volo.CmsKit.EntityFrameworkCore.Tests/Volo.CmsKit.EntityFrameworkCore.Tests.csproj +++ b/modules/cms-kit/test/Volo.CmsKit.EntityFrameworkCore.Tests/Volo.CmsKit.EntityFrameworkCore.Tests.csproj @@ -1,7 +1,5 @@ - - net5.0 Volo.CmsKit diff --git a/modules/cms-kit/test/Volo.CmsKit.HttpApi.Client.ConsoleTestApp/Volo.CmsKit.HttpApi.Client.ConsoleTestApp.csproj b/modules/cms-kit/test/Volo.CmsKit.HttpApi.Client.ConsoleTestApp/Volo.CmsKit.HttpApi.Client.ConsoleTestApp.csproj index 7c406cf142..16d88cd7f6 100644 --- a/modules/cms-kit/test/Volo.CmsKit.HttpApi.Client.ConsoleTestApp/Volo.CmsKit.HttpApi.Client.ConsoleTestApp.csproj +++ b/modules/cms-kit/test/Volo.CmsKit.HttpApi.Client.ConsoleTestApp/Volo.CmsKit.HttpApi.Client.ConsoleTestApp.csproj @@ -7,7 +7,7 @@ - + diff --git a/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/Volo.CmsKit.MongoDB.Tests.csproj b/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/Volo.CmsKit.MongoDB.Tests.csproj index d21c219bab..9591191e60 100644 --- a/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/Volo.CmsKit.MongoDB.Tests.csproj +++ b/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/Volo.CmsKit.MongoDB.Tests.csproj @@ -1,7 +1,5 @@ - - net5.0 Volo.CmsKit diff --git a/modules/cms-kit/test/Volo.CmsKit.TestBase/Volo.CmsKit.TestBase.csproj b/modules/cms-kit/test/Volo.CmsKit.TestBase/Volo.CmsKit.TestBase.csproj index 89d35f3aa9..35c8c151ea 100644 --- a/modules/cms-kit/test/Volo.CmsKit.TestBase/Volo.CmsKit.TestBase.csproj +++ b/modules/cms-kit/test/Volo.CmsKit.TestBase/Volo.CmsKit.TestBase.csproj @@ -1,7 +1,5 @@ - - net5.0 Volo.CmsKit diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20201208084431_Added_CommitCount.Designer.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20201208084431_Added_CommitCount.Designer.cs new file mode 100644 index 0000000000..ff28c9f865 --- /dev/null +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20201208084431_Added_CommitCount.Designer.cs @@ -0,0 +1,987 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; +using VoloDocs.EntityFrameworkCore; + +namespace VoloDocs.EntityFrameworkCore.Migrations +{ + [DbContext(typeof(VoloDocsDbContext))] + [Migration("20201208084431_Added_CommitCount")] + partial class Added_CommitCount + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .UseIdentityColumns() + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.0"); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ValueType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("SourceTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique() + .HasFilter("[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL"); + + b.ToTable("AbpLinkUsers"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("bit") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("bit") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("bit") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("SecurityStamp"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("nvarchar(196)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("nvarchar(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles"); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpPermissionGrants"); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpSettings"); + }); + + modelBuilder.Entity("Volo.Docs.Documents.Document", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("EditLink") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Format") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("LanguageCode") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("LastCachedTime") + .HasColumnType("datetime2"); + + b.Property("LastSignificantUpdateTime") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetime2"); + + b.Property("LocalDirectory") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("RawRootUrl") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("RootUrl") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("Version") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.ToTable("DocsDocuments"); + }); + + modelBuilder.Entity("Volo.Docs.Documents.DocumentContributor", b => + { + b.Property("DocumentId") + .HasColumnType("uniqueidentifier"); + + b.Property("Username") + .HasColumnType("nvarchar(450)"); + + b.Property("AvatarUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("CommitCount") + .HasColumnType("int"); + + b.Property("UserProfileUrl") + .HasColumnType("nvarchar(max)"); + + b.HasKey("DocumentId", "Username"); + + b.ToTable("DocsDocumentContributors"); + }); + + modelBuilder.Entity("Volo.Docs.Projects.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("DefaultDocumentName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("DocumentStoreType") + .HasColumnType("nvarchar(max)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Format") + .HasColumnType("nvarchar(max)"); + + b.Property("LatestVersionBranchName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("MainWebsiteUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("MinimumVersion") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("NavigationDocumentName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ParametersDocumentName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ShortName") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.HasKey("Id"); + + b.ToTable("DocsProjects"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Docs.Documents.DocumentContributor", b => + { + b.HasOne("Volo.Docs.Documents.Document", null) + .WithMany("Contributors") + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Docs.Documents.Document", b => + { + b.Navigation("Contributors"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20201208084431_Added_CommitCount.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20201208084431_Added_CommitCount.cs new file mode 100644 index 0000000000..1ed082ff34 --- /dev/null +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20201208084431_Added_CommitCount.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace VoloDocs.EntityFrameworkCore.Migrations +{ + public partial class Added_CommitCount : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CommitCount", + table: "DocsDocumentContributors", + type: "int", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "CommitCount", + table: "DocsDocumentContributors"); + } + } +} diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs index 204023bf3c..112509c609 100644 --- a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .UseIdentityColumns() .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.0-rc.2.20475.6"); + .HasAnnotation("ProductVersion", "5.0.0"); modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => { @@ -782,6 +782,9 @@ namespace VoloDocs.EntityFrameworkCore.Migrations b.Property("AvatarUrl") .HasColumnType("nvarchar(max)"); + b.Property("CommitCount") + .HasColumnType("int"); + b.Property("UserProfileUrl") .HasColumnType("nvarchar(max)"); diff --git a/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj b/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj index 8244c9b6fd..739ad8f7cd 100644 --- a/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj +++ b/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj @@ -17,9 +17,9 @@
- + - + diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentContributorDto.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentContributorDto.cs index 337faf3db1..fcd049d7c9 100644 --- a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentContributorDto.cs +++ b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentContributorDto.cs @@ -10,5 +10,7 @@ namespace Volo.Docs.Documents public string UserProfileUrl { get; set; } public string AvatarUrl { get; set; } + + public int CommitCount { get; set; } } } diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/Document.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/Document.cs index c2ec85f33b..967b5939f2 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/Document.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/Document.cs @@ -87,9 +87,9 @@ namespace Volo.Docs.Documents Contributors = new List(); } - public virtual void AddContributor(string username, string userProfileUrl, string avatarUrl) + public virtual void AddContributor(string username, string userProfileUrl, string avatarUrl, int commitCount = 1) { - Contributors.AddIfNotContains(new DocumentContributor(Id, username, userProfileUrl, avatarUrl)); + Contributors.AddIfNotContains(new DocumentContributor(Id, username, userProfileUrl, avatarUrl, commitCount)); } public virtual void RemoveAllContributors() diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentContributor.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentContributor.cs index 1351b0a4ca..876686b5ff 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentContributor.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentContributor.cs @@ -9,6 +9,8 @@ namespace Volo.Docs.Documents public string Username { get; set; } + public int CommitCount { get; set; } + public string UserProfileUrl { get; set; } public string AvatarUrl { get; set; } @@ -23,12 +25,13 @@ namespace Volo.Docs.Documents return DocumentId == documentId && Username == username; } - public DocumentContributor(Guid documentId, string username, string userProfileUrl, string avatarUrl) + public DocumentContributor(Guid documentId, string username, string userProfileUrl, string avatarUrl, int commitCount = 1) { DocumentId = documentId; Username = username; UserProfileUrl = userProfileUrl; AvatarUrl = avatarUrl; + CommitCount = commitCount; } public override object[] GetKeys() diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/DocumentAuthor.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/DocumentAuthor.cs new file mode 100644 index 0000000000..f1fef91713 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/DocumentAuthor.cs @@ -0,0 +1,13 @@ +namespace Volo.Docs.GitHub.Documents +{ + public class DocumentAuthor + { + public string Login { get; set; } + + public string HtmlUrl { get; set; } + + public string AvatarUrl { get; set; } + + public int CommitCount { get; set; } + } +} diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs index ef8ea15e76..dfc79f7547 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs @@ -84,9 +84,11 @@ namespace Volo.Docs.GitHub.Documents } var authors = GetAuthors(commits); + + document.RemoveAllContributors(); foreach (var author in authors) { - document.AddContributor(author.Login, author.HtmlUrl, author.AvatarUrl); + document.AddContributor(author.Login, author.HtmlUrl, author.AvatarUrl, author.CommitCount); } return document; @@ -114,20 +116,35 @@ namespace Volo.Docs.GitHub.Documents : null; } - private static List GetAuthors(IReadOnlyList commits) + private static List GetAuthors(IReadOnlyList commits) { if (commits == null || !commits.Any()) { - return new List(); + return new List(); } - return commits + var authorsOrderedAndGrouped = commits .Where(x => x.Author != null) .Select(x => x.Author) .GroupBy(x => x.Id) - .OrderByDescending(x => x.Count()) - .Select(x => x.FirstOrDefault()) - .ToList(); + .OrderByDescending(x => x.Count()); + + var documentAuthors = new List(); + + foreach (var authorGroup in authorsOrderedAndGrouped) + { + var author = authorGroup.FirstOrDefault(); + var documentAuthor = new DocumentAuthor + { + CommitCount = authorGroup.Count(), + AvatarUrl = author.AvatarUrl, + HtmlUrl = author.HtmlUrl, + Login = author.Login + }; + documentAuthors.Add(documentAuthor); + } + + return documentAuthors; } private static DateTime GetLastCommitDate(IReadOnlyList commits) diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml index a7897eddfe..1cdfe7ca2e 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml @@ -217,7 +217,7 @@ @(L["Contributors"].Value) - @foreach (var contributor in Model.Document.Contributors) + @foreach (var contributor in Model.Document.Contributors.OrderByDescending(c=> c.CommitCount).ToList()) { 0) { + setCookies(); + } + } + }; + $('.doc-section-combobox').change(function () { setCookies(); clearQueryString(); location.reload(); }); + initCookies(); setQueryString(); }; diff --git a/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj b/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj index 8561d8b72d..90d738f09e 100644 --- a/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj +++ b/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj @@ -23,7 +23,7 @@ - + diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor.cs index ea07a96b46..ada5853f6a 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor.cs @@ -16,26 +16,26 @@ namespace Volo.Abp.FeatureManagement.Blazor.Components public partial class FeatureManagementModal { [Inject] protected IFeatureAppService FeatureAppService { get; set; } - + [Inject] protected IUiMessageService UiMessageService { get; set; } - + [Inject] protected IStringLocalizerFactory HtmlLocalizerFactory { get; set; } - + [Inject] protected IOptions LocalizationOptions { get; set; } protected Modal Modal; - + protected string ProviderName; protected string ProviderKey; protected string SelectedTabName; - + protected List Groups { get; set; } protected Dictionary ToggleValues; protected Dictionary SelectionStringValues; - + public virtual async Task OpenAsync([NotNull]string providerName, string providerKey = null) { ProviderName = providerName; @@ -43,11 +43,11 @@ namespace Volo.Abp.FeatureManagement.Blazor.Components ToggleValues = new Dictionary(); SelectionStringValues = new Dictionary(); - + Groups = (await FeatureAppService.GetAsync(ProviderName, ProviderKey)).Groups; SelectedTabName = GetNormalizedGroupName(Groups.First().Name); - + foreach (var featureGroupDto in Groups) { foreach (var featureDto in featureGroupDto.Features) @@ -66,13 +66,13 @@ namespace Volo.Abp.FeatureManagement.Blazor.Components Modal.Show(); } - + public virtual Task CloseModal() { Modal.Hide(); return Task.CompletedTask; } - + protected virtual async Task SaveAsync() { var features = new UpdateFeaturesDto @@ -80,21 +80,21 @@ namespace Volo.Abp.FeatureManagement.Blazor.Components Features = Groups.SelectMany(g => g.Features).Select(f => new UpdateFeatureDto { Name = f.Name, - Value = f.ValueType is ToggleStringValueType ? ToggleValues[f.Name].ToString() : + Value = f.ValueType is ToggleStringValueType ? ToggleValues[f.Name].ToString() : f.ValueType is SelectionStringValueType ? SelectionStringValues[f.Name] : f.Value }).ToList() }; - + await FeatureAppService.UpdateAsync(ProviderName, ProviderKey, features); - + Modal.Hide(); } - + protected virtual string GetNormalizedGroupName(string name) { return "FeatureGroup_" + name.Replace(".", "_"); } - + protected virtual bool IsDisabled(string providerName) { return providerName != ProviderName && providerName != DefaultValueFeatureValueProvider.ProviderName; @@ -102,7 +102,7 @@ namespace Volo.Abp.FeatureManagement.Blazor.Components protected virtual async Task OnFeatureValueChangedAsync(string value, FeatureDto feature) { - if (feature.ValueType.Validator.IsValid(value)) + if (feature?.ValueType?.Validator.IsValid(value) == true) { feature.Value = value; } @@ -116,11 +116,11 @@ namespace Volo.Abp.FeatureManagement.Blazor.Components { SelectionStringValues[featureName] = value; } - + protected virtual IStringLocalizer CreateStringLocalizer(string resourceName) { var resource = LocalizationOptions.Value.Resources.Values.FirstOrDefault(x => x.ResourceName == resourceName); return HtmlLocalizerFactory.Create(resource != null ? resource.ResourceType : LocalizationOptions.Value.DefaultResourceType); } } -} \ No newline at end of file +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs index 6d7c6d59c2..c59bf0589f 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs @@ -132,7 +132,7 @@ namespace Volo.Abp.FeatureManagement var feature = FeatureDefinitionManager.Get(name); - if (!feature.ValueType.Validator.IsValid(value)) + if (feature?.ValueType?.Validator.IsValid(value) == false) { throw new FeatureValueInvalidException(feature.DisplayName.Localize(StringLocalizerFactory)); } diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityWebMainMenuContributor.cs b/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityWebMainMenuContributor.cs index 3198e1335d..5e5714a851 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityWebMainMenuContributor.cs +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityWebMainMenuContributor.cs @@ -27,12 +27,12 @@ namespace Volo.Abp.Identity.Blazor if (hasRolePermission) { - identityMenuItem.AddItem(new ApplicationMenuItem(IdentityMenuNames.Roles, l["Roles"], url: "/identity/roles")); + identityMenuItem.AddItem(new ApplicationMenuItem(IdentityMenuNames.Roles, l["Roles"], url: "identity/roles")); } if (hasUserPermission) { - identityMenuItem.AddItem(new ApplicationMenuItem(IdentityMenuNames.Users, l["Users"], url: "/identity/users")); + identityMenuItem.AddItem(new ApplicationMenuItem(IdentityMenuNames.Users, l["Users"], url: "identity/users")); } } } diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor index a1f410264b..f20f4165e8 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor @@ -104,7 +104,7 @@ - + @@ -142,7 +142,7 @@ - + diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor index 73d8492f8f..a371d4a646 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor @@ -176,7 +176,7 @@ - + @@ -287,7 +287,7 @@ - + diff --git a/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebModule.cs b/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebModule.cs index ce26e91e20..511455bab3 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebModule.cs @@ -2,9 +2,11 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars; using Volo.Abp.AutoMapper; using Volo.Abp.Identity.Localization; using Volo.Abp.Identity.Web.Navigation; +using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectExtending.Modularity; @@ -64,6 +66,34 @@ namespace Volo.Abp.Identity.Web options.Conventions.AuthorizePage("/Identity/Roles/CreateModal", IdentityPermissions.Roles.Create); options.Conventions.AuthorizePage("/Identity/Roles/EditModal", IdentityPermissions.Roles.Update); }); + + + Configure(options => + { + options.Configure( + toolbar => + { + toolbar.AddButton( + LocalizableString.Create("NewUser"), + icon: "plus", + name: "CreateUser", + requiredPolicyName: IdentityPermissions.Users.Create + ); + } + ); + + options.Configure( + toolbar => + { + toolbar.AddButton( + LocalizableString.Create("NewRole"), + icon: "plus", + name: "CreateRole", + requiredPolicyName: IdentityPermissions.Roles.Create + ); + } + ); + }); } public override void PostConfigureServices(ServiceConfigurationContext context) diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/Index.cshtml b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/Index.cshtml index 734fc40fe5..30e42694e6 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/Index.cshtml +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/Index.cshtml @@ -2,6 +2,7 @@ @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Mvc.Localization @using Volo.Abp.AspNetCore.Mvc.UI.Layout +@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageToolbar @using Volo.Abp.Identity @using Volo.Abp.Identity.Localization @using Volo.Abp.Identity.Web.Navigation @@ -33,10 +34,7 @@ @L["Roles"] - @if (await Authorization.IsGrantedAsync(IdentityPermissions.Roles.Create)) - { - - } + @await Component.InvokeAsync(typeof(AbpPageToolbarViewComponent), new { pageName = typeof(IndexModel).FullName }) diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/Index.cshtml b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/Index.cshtml index ee9192d58f..5904cab2fa 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/Index.cshtml +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/Index.cshtml @@ -2,6 +2,7 @@ @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Mvc.Localization @using Volo.Abp.AspNetCore.Mvc.UI.Layout +@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageToolbar @using Volo.Abp.Identity @using Volo.Abp.Identity.Localization @using Volo.Abp.Identity.Web.Navigation @@ -34,10 +35,7 @@ @L["Users"] - @if (await Authorization.IsGrantedAsync(IdentityPermissions.Users.Create)) - { - - } + @await Component.InvokeAsync(typeof(AbpPageToolbarViewComponent), new { pageName = typeof(IndexModel).FullName }) diff --git a/modules/identityserver/common.props b/modules/identityserver/common.props deleted file mode 100644 index 7f5a705307..0000000000 --- a/modules/identityserver/common.props +++ /dev/null @@ -1,16 +0,0 @@ - - - latest - 0.3.0 - $(NoWarn);CS1591;CS0436 - http://www.aspnetboilerplate.com/images/abp_nupkg.png - http://abp.io - git - https://github.com/volosoft/abp/ - - - - - - - \ No newline at end of file diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiScopes/IApiScopeeRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiScopes/IApiScopeRepository.cs similarity index 100% rename from modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiScopes/IApiScopeeRepository.cs rename to modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiScopes/IApiScopeRepository.cs diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupBackgroundWorker.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupBackgroundWorker.cs index 66aa42a1df..c424f9513c 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupBackgroundWorker.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupBackgroundWorker.cs @@ -11,7 +11,7 @@ namespace Volo.Abp.IdentityServer.Tokens protected TokenCleanupOptions Options { get; } public TokenCleanupBackgroundWorker( - AbpTimer timer, + AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory, IOptions options) : base( diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Menus/SettingManagementMenuContributor.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Menus/SettingManagementMenuContributor.cs index 44343e0498..531613b77c 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Menus/SettingManagementMenuContributor.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Menus/SettingManagementMenuContributor.cs @@ -37,7 +37,7 @@ namespace Volo.Abp.SettingManagement.Blazor.Menus new ApplicationMenuItem( SettingManagementMenus.GroupName, l["Settings"], - "/setting-management", + "setting-management", icon: "fa fa-cog" ) ); diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Navigation/TenantManagementBlazorMenuContributor.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Navigation/TenantManagementBlazorMenuContributor.cs index c1d6e9ac7a..03bfd6b2d2 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Navigation/TenantManagementBlazorMenuContributor.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Navigation/TenantManagementBlazorMenuContributor.cs @@ -22,7 +22,7 @@ namespace Volo.Abp.TenantManagement.Blazor.Navigation if (await context.IsGrantedAsync(TenantManagementPermissions.Tenants.Default)) { - tenantManagementMenuItem.AddItem(new ApplicationMenuItem(TenantManagementMenuNames.Tenants, l["Tenants"], url: "/tenant-management/tenants")); + tenantManagementMenuItem.AddItem(new ApplicationMenuItem(TenantManagementMenuNames.Tenants, l["Tenants"], url: "tenant-management/tenants")); } } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Pages/TenantManagement/TenantManagement.razor b/modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Pages/TenantManagement/TenantManagement.razor index 722458e82c..f1ced268ca 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Pages/TenantManagement/TenantManagement.razor +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Pages/TenantManagement/TenantManagement.razor @@ -114,7 +114,7 @@ - + @@ -148,7 +148,7 @@ - + @@ -187,7 +187,7 @@ - + diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/AbpTenantManagementWebModule.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/AbpTenantManagementWebModule.cs index e993ea2c63..e03a7ec2a2 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/AbpTenantManagementWebModule.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/AbpTenantManagementWebModule.cs @@ -2,8 +2,10 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars; using Volo.Abp.AutoMapper; using Volo.Abp.FeatureManagement; +using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectExtending.Modularity; @@ -61,6 +63,28 @@ namespace Volo.Abp.TenantManagement.Web options.Conventions.AuthorizePage("/TenantManagement/Tenants/EditModal", TenantManagementPermissions.Tenants.Update); options.Conventions.AuthorizePage("/TenantManagement/Tenants/ConnectionStrings", TenantManagementPermissions.Tenants.ManageConnectionStrings); }); + + Configure(options => + { + options.Configure( + toolbar => + { + toolbar.AddButton( + LocalizableString.Create("ManageHostFeatures"), + icon: "cog", + name: "ManageHostFeatures", + requiredPolicyName: FeatureManagementPermissions.ManageHostFeatures + ); + + toolbar.AddButton( + LocalizableString.Create("NewTenant"), + icon: "plus", + name: "CreateTenant", + requiredPolicyName: TenantManagementPermissions.Tenants.Create + ); + } + ); + }); } public override void PostConfigureServices(ServiceConfigurationContext context) diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml index bb972b02d8..67fd507bcc 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml @@ -2,6 +2,7 @@ @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Mvc.Localization @using Volo.Abp.AspNetCore.Mvc.UI.Layout +@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageToolbar @using Volo.Abp.FeatureManagement @using Volo.Abp.TenantManagement @using Volo.Abp.TenantManagement.Localization @@ -30,14 +31,7 @@ @L["Tenants"] - @if (await Authorization.IsGrantedAsync(FeatureManagementPermissions.ManageHostFeatures)) - { - - } - @if (await Authorization.IsGrantedAsync(TenantManagementPermissions.Tenants.Create)) - { - - } + @await Component.InvokeAsync(typeof(AbpPageToolbarViewComponent), new { pageName = typeof(IndexModel).FullName }) diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Volo.Abp.VirtualFileExplorer.DemoApp.csproj b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Volo.Abp.VirtualFileExplorer.DemoApp.csproj index 6cfb1efc40..b1c78debfd 100644 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Volo.Abp.VirtualFileExplorer.DemoApp.csproj +++ b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Volo.Abp.VirtualFileExplorer.DemoApp.csproj @@ -6,7 +6,7 @@ - + diff --git a/npm/ng-packs/packages/components/package.json b/npm/ng-packs/packages/components/package.json index 3d4d25dd56..da5038f1f2 100644 --- a/npm/ng-packs/packages/components/package.json +++ b/npm/ng-packs/packages/components/package.json @@ -8,6 +8,7 @@ }, "peerDependencies": { "@abp/ng.core": ">=4.0.0", + "@abp/ng.theme.shared": ">=4.0.0", "@ng-bootstrap/ng-bootstrap": ">=6.0.0" }, "dependencies": { diff --git a/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.html b/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.html index b98aa7e4ff..4f4aaf472d 100644 --- a/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.html +++ b/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.html @@ -7,10 +7,12 @@ [nzData]="nodes" [nzTreeTemplate]="treeTemplate" [nzExpandedKeys]="expandedKeys" - [nzExpandedIcon]="expandedIconTemplate?.template" + [nzExpandedIcon]="expandedIconTemplate?.template || defaultIconTemplate" (nzExpandChange)="onExpandedKeysChange($event)" (nzCheckBoxChange)="onCheckboxChange($event)" (nzOnDrop)="onDrop($event)" + [nzNoAnimation]="noAnimation" + (nzContextMenu)="dropdowns[$event.node?.key]?.toggle()" >
- + - - {{ node.title }} - + +
+ +
-
- -
- +
+ +
+ +
-
+ + + + {{ node.title }} +
+ + + + + + + + + + + + + + + + diff --git a/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.scss b/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.scss index 113996455f..07ca018f0d 100644 --- a/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.scss +++ b/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.scss @@ -27,18 +27,6 @@ cursor: pointer; padding-left: 8px; border: 1px solid transparent; - - &:hover { - background-color: transparent; - border: 1px solid var(--primary); - color: var(--text-color); - } - - &.selected { - background-color: transparent; - color: var(--white); - background-color: var(--primary); - } } .ellipsis { diff --git a/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.ts b/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.ts index 7ba6280c0b..3f6179a5b2 100644 --- a/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.ts +++ b/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.ts @@ -11,6 +11,7 @@ import { NzFormatEmitEvent, NzFormatBeforeDropEvent } from 'ng-zorro-antd/tree'; import { of } from 'rxjs'; import { TreeNodeTemplateDirective } from '../templates/tree-node-template.directive'; import { ExpandedIconTemplateDirective } from '../templates/expanded-icon-template.directive'; +import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'; export type DropEvent = NzFormatEmitEvent & { pos: number }; @@ -26,6 +27,8 @@ export type DropEvent = NzFormatEmitEvent & { pos: number }; export class TreeComponent { dropPosition: number; + dropdowns = {} as { [key: string]: NgbDropdown }; + @ContentChild('menu') menu: TemplateRef; @ContentChild(TreeNodeTemplateDirective) customNodeTemplate: TreeNodeTemplateDirective; @ContentChild(ExpandedIconTemplateDirective) expandedIconTemplate: ExpandedIconTemplateDirective; @@ -33,6 +36,7 @@ export class TreeComponent { @Output() readonly expandedKeysChange = new EventEmitter(); @Output() readonly selectedNodeChange = new EventEmitter(); @Output() readonly dropOver = new EventEmitter(); + @Input() noAnimation = true; @Input() draggable: boolean; @Input() checkable: boolean; @Input() checkStrictly: boolean; @@ -68,4 +72,8 @@ export class TreeComponent { this.dropOver.emit(event); } + + initDropdown(key: string, dropdown: NgbDropdown) { + this.dropdowns[key] = dropdown; + } } diff --git a/npm/ng-packs/packages/components/tree/src/lib/tree.module.ts b/npm/ng-packs/packages/components/tree/src/lib/tree.module.ts index b645a69925..2013c37588 100644 --- a/npm/ng-packs/packages/components/tree/src/lib/tree.module.ts +++ b/npm/ng-packs/packages/components/tree/src/lib/tree.module.ts @@ -1,17 +1,18 @@ -import { CommonModule } from '@angular/common'; +import { CoreModule } from '@abp/ng.core'; import { NgModule } from '@angular/core'; import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; +import { NzNoAnimationModule } from 'ng-zorro-antd/core/no-animation'; import { NzTreeModule } from 'ng-zorro-antd/tree'; import { TreeComponent } from './components/tree.component'; -import { TreeNodeTemplateDirective } from './templates/tree-node-template.directive'; import { ExpandedIconTemplateDirective } from './templates/expanded-icon-template.directive'; +import { TreeNodeTemplateDirective } from './templates/tree-node-template.directive'; const templates = [TreeNodeTemplateDirective, ExpandedIconTemplateDirective]; const exported = [...templates, TreeComponent]; @NgModule({ - imports: [CommonModule, NzTreeModule, NgbDropdownModule], + imports: [CoreModule, NzTreeModule, NgbDropdownModule, NzNoAnimationModule], exports: [...exported], declarations: [...exported], }) diff --git a/npm/ng-packs/packages/core/src/lib/models/dtos.ts b/npm/ng-packs/packages/core/src/lib/models/dtos.ts index bd35d90338..49c1d8e735 100644 --- a/npm/ng-packs/packages/core/src/lib/models/dtos.ts +++ b/npm/ng-packs/packages/core/src/lib/models/dtos.ts @@ -25,7 +25,7 @@ export class LimitedResultRequestDto { constructor(initialValues: Partial = {}) { for (const key in initialValues) { - if (initialValues.hasOwnProperty(key)) { + if (initialValues.hasOwnProperty(key) && initialValues[key] !== undefined) { this[key] = initialValues[key]; } } diff --git a/npm/ng-packs/packages/schematics/src/constants/volo.ts b/npm/ng-packs/packages/schematics/src/constants/volo.ts index 12aa166d66..00fde72c79 100644 --- a/npm/ng-packs/packages/schematics/src/constants/volo.ts +++ b/npm/ng-packs/packages/schematics/src/constants/volo.ts @@ -1,22 +1 @@ -import { Interface, Property } from '../models'; - export const VOLO_REGEX = /^Volo\.Abp\.(Application\.Dtos|ObjectExtending)/; - -export const VOLO_NAME_VALUE = new Interface({ - base: null, - identifier: 'NameValue', - ref: 'Volo.Abp.NameValue', - namespace: 'Volo.Abp', - properties: [ - new Property({ - name: 'name', - type: 'string', - refs: ['System.String'], - }), - new Property({ - name: 'value', - type: 'T', - refs: ['T'], - }), - ], -}); diff --git a/npm/ng-packs/packages/schematics/src/enums/exception.ts b/npm/ng-packs/packages/schematics/src/enums/exception.ts index b267ad6674..b7b206cbf6 100644 --- a/npm/ng-packs/packages/schematics/src/enums/exception.ts +++ b/npm/ng-packs/packages/schematics/src/enums/exception.ts @@ -5,7 +5,7 @@ export const enum Exception { InvalidModule = '[Invalid Module] Backend module "{0}" does not exist in API definition.', InvalidApiDefinition = '[Invalid API Definition] The provided API definition is invalid.', InvalidWorkspace = '[Invalid Workspace] The angular.json should be a valid JSON file.', - NoApi = '[API Not Available] Please double-check the URL in the source project environment and make sure your application is up and running.', + NoApi = '[API Not Available] Request to {0} is unsuccessful. Please double-check the URL in the source project environment and make sure your application is up and running.', NoProject = '[Project Not Found] Either define a default project in your workspace or specify the project name in schematics options.', NoProxyConfig = '[Proxy Config Not Found] There is no JSON file at "{0}".', NoTypeDefinition = '[Type Definition Not Found] There is no type definition for "{0}".', diff --git a/npm/ng-packs/packages/schematics/src/models/model.ts b/npm/ng-packs/packages/schematics/src/models/model.ts index 6c7feb318d..048c08a1b0 100644 --- a/npm/ng-packs/packages/schematics/src/models/model.ts +++ b/npm/ng-packs/packages/schematics/src/models/model.ts @@ -1,43 +1,97 @@ import { Import } from './import'; -import { Omissible } from './util'; +import { Options } from './util'; export class Model { - imports: Import[] = []; - interfaces: Interface[] = []; - namespace: string; - path: string; + readonly imports: Import[] = []; + readonly interfaces: Interface[] = []; + readonly namespace: string; + readonly path: string; constructor(options: ModelOptions) { Object.assign(this, options); } } -export type ModelOptions = Omissible; +export type ModelOptions = Options; export class Interface { - base: string | null; - identifier: string; - namespace: string; - properties: Property[] = []; - ref: string; + readonly base: string | null; + readonly identifier: string; + readonly namespace: string; + readonly generics: Generic[] = []; + readonly properties: Property[] = []; + readonly ref: string; constructor(options: InterfaceOptions) { Object.assign(this, options); } } -export type InterfaceOptions = Omissible; +export type InterfaceOptions = Options; -export class Property { - name: string; - type: string; - default = ''; - optional: '' | '?' = ''; - refs: string[] = []; +abstract class TypeRef { + readonly refs: string[] = []; - constructor(options: PropertyOptions) { + protected _type = ''; + get type() { + return this._type; + } + set type(value: string) { + if (!value) return; + this._type = value; + } + + protected _default = ''; + get default() { + return this._default; + } + set default(value: string) { + if (!value) return; + this._default = ` = ${value}`; + } + + constructor(options: TypeRefOptions) { Object.assign(this, options); } + + setDefault(value: string) { + this.default = value; + } + + setType(value: string) { + this.type = value; + } +} + +type TypeRefOptionalKeys = 'default' | 'refs'; +type TypeRefOptions = Options; + +export class Generic extends TypeRef { + constructor(options: GenericOptions) { + super(options); + } +} + +export type GenericOptions = Options; + +export class Property extends TypeRef { + readonly name: string; + private _optional: '' | '?' = ''; + get optional() { + return this.default ? '' : this._optional; + } + + set optional(value: '' | '?') { + this._optional = value; + } + + constructor(options: PropertyOptions) { + super(options); + } + + setOptional(isOptional: boolean) { + this.optional = isOptional ? '?' : ''; + } } -export type PropertyOptions = Omissible; +export type PropertyOptions = Options; diff --git a/npm/ng-packs/packages/schematics/src/models/util.ts b/npm/ng-packs/packages/schematics/src/models/util.ts index 5ff732ccfe..0588ed7d5b 100644 --- a/npm/ng-packs/packages/schematics/src/models/util.ts +++ b/npm/ng-packs/packages/schematics/src/models/util.ts @@ -1,2 +1,16 @@ // Omissible (given keys will become optional) export type Omissible = Partial> & Omit; + +// ExcludeKeys (keys will be excluded based on their type) +type ExcludeKeys = Exclude< + { + [Key in keyof Type]: Type[Key] extends Excluded ? never : Key; + }[keyof Type], + never +>; + +// tslint:disable-next-line: ban-types +type ExcludeMethods = Pick>; + +// Options (methods will be omitted, given keys will become optional) +export type Options> = Omissible, K>; diff --git a/npm/ng-packs/packages/schematics/src/utils/generics.ts b/npm/ng-packs/packages/schematics/src/utils/generics.ts new file mode 100644 index 0000000000..8dc7fb2629 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/utils/generics.ts @@ -0,0 +1,100 @@ +import { Generic } from '../models'; + +export class GenericsCollector { + private _generics: Generic[] = []; + get generics() { + return this._generics; + } + + apply = (value: string, index: number) => { + const generic = this.get(index); + if (generic) { + if (!generic.type) generic.setType(value); + return value + generic.default; + } + + return value; + }; + + constructor(private getTypeIdentifier = (type: string) => type) {} + + private createGeneric(type: string, ref: string, defaultValue: string) { + const _default = this.getTypeIdentifier(defaultValue); + const refs = [generateRefWithPlaceholders(ref)]; + const generic = new Generic({ type, default: _default, refs }); + return generic; + } + + private register(index: number, generic: Generic) { + const existing = this.get(index); + if (existing) { + existing.setDefault(generic.default); + existing.setType(generic.type); + } else this.set(index, generic); + } + + collect(generics: string[], genericArguments: string[]) { + generics.forEach((ref, i) => { + const generic = this.createGeneric( + genericArguments[i], + ref, + genericArguments.includes(ref) ? '' : ref, + ); + this.register(i, generic); + }); + } + + get(index: number) { + return this.generics[index]; + } + + set(index: number, value: Generic) { + this.generics[index] = value; + } + + reset() { + this._generics = []; + } +} + +export function generateRefWithPlaceholders(sourceType: string) { + let { identifier, generics } = extractGenerics(sourceType); + + identifier = identifier; + generics = generics.map((_, i) => `T${i}`); + + return generics.length ? `${identifier}<${generics}>` : identifier; +} + +export function extractSimpleGenerics(sourceType: string) { + const { identifier, generics } = extractGenerics(sourceType); + + return { + identifier: getLastSegment(identifier), + generics: generics.map(getLastSegment), + }; +} + +export function extractGenerics(sourceType: string) { + const regex = /(?[^<]+)(<(?.+)>)?/g; + const { identifier = '', generics = '' } = regex.exec(sourceType)?.groups ?? {}; + + return { + identifier, + generics: generics.split(/,\s*/).filter(Boolean), + }; +} + +function getLastSegment(str: string) { + return str.split('.').pop()!; +} + +export function replacePlaceholdersWithGenerics( + type: string, + generics: string[], + genericsCollector: GenericsCollector, +) { + return generics + .map(genericsCollector.apply) + .reduce((acc, v, i) => acc.replace(new RegExp(`([<, ])T${i}([,>])`, 'g'), `$1${v}$2`), type); +} diff --git a/npm/ng-packs/packages/schematics/src/utils/index.ts b/npm/ng-packs/packages/schematics/src/utils/index.ts index 178920dccc..e6df05b2e2 100644 --- a/npm/ng-packs/packages/schematics/src/utils/index.ts +++ b/npm/ng-packs/packages/schematics/src/utils/index.ts @@ -5,6 +5,7 @@ export * from './barrel'; export * from './common'; export * from './enum'; export * from './file'; +export * from './generics'; export * from './import'; export * from './model'; export * from './namespace'; diff --git a/npm/ng-packs/packages/schematics/src/utils/model.ts b/npm/ng-packs/packages/schematics/src/utils/model.ts index fc8dde37c1..49d3c0fcf5 100644 --- a/npm/ng-packs/packages/schematics/src/utils/model.ts +++ b/npm/ng-packs/packages/schematics/src/utils/model.ts @@ -1,5 +1,11 @@ -import { VOLO_NAME_VALUE, VOLO_REGEX } from '../constants'; +import { VOLO_REGEX } from '../constants'; import { Interface, Model, Property, PropertyDef, Type, TypeWithEnum } from '../models'; +import { + extractGenerics, + generateRefWithPlaceholders, + GenericsCollector, + replacePlaceholdersWithGenerics, +} from './generics'; import { parseNamespace } from './namespace'; import { relativePathToModel } from './path'; import { camel } from './text'; @@ -8,6 +14,7 @@ import { createTypeParser, createTypeSimplifier, createTypesToImportsReducer, + extendsSelf, removeTypeModifiers, } from './type'; @@ -27,6 +34,7 @@ export function createImportRefsToModelReducer(params: ModelGeneratorParams) { return (models: Model[], importRefs: string[]) => { const enums: string[] = []; const interfaces = importRefs.reduce(reduceImportRefsToInterfaces, []); + sortInterfaces(interfaces); interfaces.forEach(_interface => { @@ -40,12 +48,9 @@ export function createImportRefsToModelReducer(params: ModelGeneratorParams) { const index = models.findIndex(m => m.namespace === _interface.namespace); if (index > -1) { if (models[index].interfaces.some(i => i.identifier === _interface.identifier)) return; - if (_interface.ref.startsWith(VOLO_NAME_VALUE.ref)) return; models[index].interfaces.push(_interface); } else { - if (_interface.ref.startsWith(VOLO_NAME_VALUE.ref)) _interface = VOLO_NAME_VALUE; - const { namespace } = _interface; models.push( @@ -70,7 +75,7 @@ export function createImportRefsToModelReducer(params: ModelGeneratorParams) { isEnum: false, }); - _interface.properties.forEach(prop => { + [..._interface.properties, ..._interface.generics].forEach(prop => { prop.refs.forEach(ref => { const propType = types[ref]; if (!propType) return; @@ -100,38 +105,50 @@ export function createImportRefToInterfaceReducerCreator(params: ModelGeneratorP const parseType = createTypeParser(removeTypeModifiers); const simplifyType = createTypeSimplifier(); const getIdentifier = (type: string) => removeTypeModifiers(simplifyType(type)); + const genericsCollector = new GenericsCollector(getIdentifier); return reduceRefsToInterfaces; - function reduceRefsToInterfaces(interfaces: Interface[], ref: string) { + function reduceRefsToInterfaces(interfaces: Interface[], ref: string): Interface[] { const typeDef = types[ref]; if (!typeDef) return interfaces; const namespace = parseNamespace(solution, ref); - const identifier = (typeDef.genericArguments ?? []).reduce( - (acc, t, i) => acc.replace(`T${i}`, t), - getIdentifier(ref), - ); + let { baseType: base, genericArguments } = typeDef; + genericArguments = genericArguments || []; + let identifier = getIdentifier(ref); + identifier = replacePlaceholdersWithGenerics(identifier, genericArguments, genericsCollector); + + if (base) { + if (extendsSelf(ref, base)) { + genericsCollector.collect(extractGenerics(base).generics, genericArguments); + return reduceRefsToInterfaces(interfaces, generateRefWithPlaceholders(base)); + } else { + base = getIdentifier(base); + } + } - const base = typeDef.baseType ? getIdentifier(typeDef.baseType) : null; - const _interface = new Interface({ identifier, base, namespace, ref }); + const { generics } = genericsCollector; + const _interface = new Interface({ identifier, base, namespace, ref, generics }); + genericsCollector.reset(); typeDef.properties?.forEach(prop => { const name = camel(prop.name); - const optional = isOptionalProperty(prop) ? '?' : ''; const type = simplifyType(prop.typeSimple); const refs = parseType(prop.type).reduce( (acc: string[], r) => acc.concat(parseGenerics(r).toGenerics()), [], ); + const property = new Property({ name, type, refs }); + property.setOptional(isOptionalProperty(prop)); - _interface.properties.push(new Property({ name, optional, type, refs })); + _interface.properties.push(property); }); interfaces.push(_interface); - return _interface.properties + return [..._interface.properties, ..._interface.generics] .reduce((refs, prop) => { prop.refs.forEach(type => { if (types[type]?.isEnum) return; @@ -142,7 +159,7 @@ export function createImportRefToInterfaceReducerCreator(params: ModelGeneratorP return refs; }, []) .concat(base ? parseGenerics(typeDef.baseType!).toGenerics() : []) - .reduce(reduceRefsToInterfaces, interfaces); + .reduce(reduceRefsToInterfaces, interfaces); } } diff --git a/npm/ng-packs/packages/schematics/src/utils/service.ts b/npm/ng-packs/packages/schematics/src/utils/service.ts index b8a2d692b2..70655c821d 100644 --- a/npm/ng-packs/packages/schematics/src/utils/service.ts +++ b/npm/ng-packs/packages/schematics/src/utils/service.ts @@ -83,8 +83,8 @@ export function createActionToSignatureMapper() { signature.parameters = action.parametersOnMethod.map(p => { const type = adaptType(p.typeSimple); const parameter = new Property({ name: p.name, type }); - if (p.defaultValue) parameter.default = ` = ${p.defaultValue}`; - else if (p.isOptional) parameter.optional = '?'; + parameter.setDefault(p.defaultValue); + parameter.setOptional(p.isOptional); return parameter; }); diff --git a/npm/ng-packs/packages/schematics/src/utils/source.ts b/npm/ng-packs/packages/schematics/src/utils/source.ts index e1e965744f..a5f0dd1232 100644 --- a/npm/ng-packs/packages/schematics/src/utils/source.ts +++ b/npm/ng-packs/packages/schematics/src/utils/source.ts @@ -36,7 +36,7 @@ async function getApiDefinition(sourceUrl: string) { } catch ({ response }) { // handle redirects if (!response?.body || response.statusCode >= 400) - throw new SchematicsException(Exception.NoApi); + throw new SchematicsException(interpolate(Exception.NoApi, url)); body = response.body; } diff --git a/npm/ng-packs/packages/schematics/src/utils/tree.ts b/npm/ng-packs/packages/schematics/src/utils/tree.ts index d142032255..5fd8414f0c 100644 --- a/npm/ng-packs/packages/schematics/src/utils/tree.ts +++ b/npm/ng-packs/packages/schematics/src/utils/tree.ts @@ -21,7 +21,7 @@ export class TypeNode { if (!self) return ''; - const representation = self + this.children.filter(String || Boolean).join(', '); + const representation = self + this.children.filter(String).join(', '); if (!this.parent) return representation; diff --git a/npm/ng-packs/packages/schematics/src/utils/type.ts b/npm/ng-packs/packages/schematics/src/utils/type.ts index 781794c463..a087392d40 100644 --- a/npm/ng-packs/packages/schematics/src/utils/type.ts +++ b/npm/ng-packs/packages/schematics/src/utils/type.ts @@ -1,7 +1,7 @@ -import { SYSTEM_TYPES } from '../constants'; -import { VOLO_REGEX } from '../constants/volo'; +import { SYSTEM_TYPES, VOLO_REGEX } from '../constants'; import { eImportKeyword } from '../enums'; import { Import, TypeWithEnum } from '../models'; +import { extractSimpleGenerics } from './generics'; import { parseNamespace } from './namespace'; import { relativePathToEnum, relativePathToModel } from './path'; import { parseGenerics } from './tree'; @@ -15,14 +15,9 @@ export function createTypeSimplifier() { type = /any.+)<.*(?<=[\.<])(?.+)>/gm); - const { generic, genericType } = regexp.exec(type)?.groups ?? {}; + const { identifier, generics } = extractSimpleGenerics(type); - return generic - ? generic === 'any' - ? 'any' - : `${generic}<${genericType}>` - : type.split('.').pop()!; + return generics.length ? `${identifier}<${generics.join(', ')}>` : identifier; }); return (type: string) => { @@ -40,9 +35,7 @@ export function createTypeParser(replacerFn = (t: string) => t) { export function createTypeNormalizer(replacerFn = (t: string) => t) { return (type: string) => { - type = normalizeTypeAnnotations(type); - - return replacerFn(type); + return replacerFn(normalizeTypeAnnotations(type)); }; } @@ -56,8 +49,7 @@ export function flattenDictionaryTypes(types: string[], type: string) { } export function normalizeTypeAnnotations(type: string) { - type = type.replace(/\[(.+)+\]/g, '$1[]'); - return type.replace(/\?/g, ''); + return type.replace(/\[(.+)+\]/g, '$1[]').replace(/\?/g, ''); } export function removeGenerics(type: string) { @@ -115,3 +107,8 @@ export function createTypeAdapter() { const simplifyType = createTypeSimplifier(); return (type: string) => parseGenerics(type, node => simplifyType(node.data)).toString(); } + +// naming here is depictive only +export function extendsSelf(type: string, base: string) { + return removeGenerics(base) === removeGenerics(type); +} diff --git a/nupkg/common.ps1 b/nupkg/common.ps1 index 98effbe598..29249ef3f4 100644 --- a/nupkg/common.ps1 +++ b/nupkg/common.ps1 @@ -87,7 +87,7 @@ $projects = ( "framework/src/Volo.Abp.EntityFrameworkCore", "framework/src/Volo.Abp.EntityFrameworkCore.MySQL", # "framework/src/Volo.Abp.EntityFrameworkCore.Oracle", - # "framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart", + "framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart", "framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql", "framework/src/Volo.Abp.EntityFrameworkCore.Sqlite", "framework/src/Volo.Abp.EntityFrameworkCore.SqlServer", diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Menus/MyProjectNameMenuContributor.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Menus/MyProjectNameMenuContributor.cs index 8b5aebacce..7f8964d6cd 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Menus/MyProjectNameMenuContributor.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Menus/MyProjectNameMenuContributor.cs @@ -39,7 +39,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Menus new ApplicationMenuItem( MyProjectNameMenus.Home, l["Menu:Home"], - "/", + "", icon: "fas fa-home" ) ); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj index a7cfa2e681..9bc6fb7092 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj index 4d5b4c51f7..6bf2650ea9 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj @@ -23,7 +23,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/en.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/en.json index baa9fe753e..d2a6a9831e 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/en.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/en.json @@ -5,4 +5,4 @@ "Welcome": "Welcome", "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io." } -} \ No newline at end of file +} diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj index ae9ce4c4d2..c6639bbad7 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj @@ -25,7 +25,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations.csproj index 5803aac5a0..1d2226ee96 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations.csproj @@ -12,7 +12,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj index 2c2569a98c..6e3ccfa0ff 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj @@ -12,9 +12,9 @@ - - - + + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyCompanyName.MyProjectName.HttpApi.HostWithIds.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyCompanyName.MyProjectName.HttpApi.HostWithIds.csproj index 05d08e875c..d374c7feb6 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyCompanyName.MyProjectName.HttpApi.HostWithIds.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyCompanyName.MyProjectName.HttpApi.HostWithIds.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj index 66da2cc100..333268deef 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj @@ -34,8 +34,8 @@ - - + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj index 47dbf3b45b..57347aca90 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj @@ -18,7 +18,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj index 7386e0aa09..fce2337c45 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj @@ -34,7 +34,7 @@ - + diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj index 3e102fa6e3..e78ce77d08 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj @@ -22,8 +22,8 @@ - - + + diff --git a/templates/console/common.props b/templates/console/common.props index 233f41c1ba..7e29afcfb8 100644 --- a/templates/console/common.props +++ b/templates/console/common.props @@ -4,9 +4,4 @@ 0.1.0 $(NoWarn);CS1591;CS0436 - - - - - \ No newline at end of file diff --git a/templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj b/templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj index 4f91776d39..2f8497b830 100644 --- a/templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj +++ b/templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj @@ -12,7 +12,7 @@ - + diff --git a/templates/module/aspnet-core/common.props b/templates/module/aspnet-core/common.props index 420d9c492c..c1ff420edf 100644 --- a/templates/module/aspnet-core/common.props +++ b/templates/module/aspnet-core/common.props @@ -3,11 +3,6 @@ latest 0.1.0 $(NoWarn);CS1591;CS0436 - module + module - - - - - \ No newline at end of file diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj index 538abc5310..444e49801f 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj @@ -10,8 +10,8 @@ - - + + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj index 10097d1f3b..1705d64e93 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj @@ -13,9 +13,9 @@ - - - + + + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj index 2ada24f679..059027f920 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj @@ -10,8 +10,8 @@ - - + + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj index 54c7c5c0ad..2476a0ff07 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj @@ -12,7 +12,7 @@ - + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj index 2017892f0b..51b82b4896 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj b/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj index b4569551d8..a28c9bee5b 100644 --- a/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj +++ b/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj @@ -13,7 +13,7 @@ - + diff --git a/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj b/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj index 616e91d7c7..4484d69a23 100644 --- a/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj +++ b/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj @@ -21,7 +21,7 @@ - + diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj index 9809a39557..265806176f 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj @@ -9,7 +9,7 @@ - + diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj index 8a48f8906d..ab46bde28b 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj @@ -20,7 +20,7 @@ - + diff --git a/templates/wpf/common.props b/templates/wpf/common.props index 233f41c1ba..7e29afcfb8 100644 --- a/templates/wpf/common.props +++ b/templates/wpf/common.props @@ -4,9 +4,4 @@ 0.1.0 $(NoWarn);CS1591;CS0436 - - - - - \ No newline at end of file diff --git a/templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj b/templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj index b5b12c84bb..c1a57201f4 100644 --- a/templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj +++ b/templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj @@ -13,7 +13,7 @@ - +