Merge branch 'dev' of https://github.com/abpframework/abp into feat/angular-v12

pull/9340/head
mehmet-erim 4 years ago
commit 4a983b83b9

3
.gitignore vendored

@ -315,3 +315,6 @@ tempkey.jwk
# ABP Analyzing files
*.abppkg.analyze.json
# appsettings.secrets.json
appsettings.secrets.json

@ -0,0 +1,69 @@
# Introducing the Lepton Theme Next Generation!
We are delighted and proud to announce that the next generation of [Lepton Theme](https://leptontheme.com/) which will be referred to as LeptonX is on the way.
At Volosoft, we care about developer experience as much as user experience. Thus, LeptonX is following the latest trends for a better user experience and provides highly customizable features that will be easy to use. Our APIs follow a strict guideline to be easy-to-use, intuitive, extendable, and replaceable. In short, we'd like LeptonX to grow into such a platform that developers (not just ABP developers) love to build their applications on top of, and end-users love to interact with.
The initial version has been built upon Bootstrap v4. Bootstrap v5 has been recently published and the ecosystem has not caught up yet. In addition, ABP packages are already dependent on Bootstrap v4, it will be easy to switch from the [Basic Theme](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Basic-Theme) or from the [Lepton Theme](https://commercial.abp.io/themes) to the LeptonX.
We believe that the bigger the community is, the better the framework turns out to be. As we have done in our other products, we will release a free-to-use version of LeptonX, a.k.a LeptonX-lite which will contain most of the basic features. With LeptonX-lite, free ABP [application startup template](https://docs.abp.io/en/abp/latest/Startup-Templates/Application)s will come with a production-ready theme, and existing applications will be able to switch from the Basic Theme to the LeptonX-lite with ease.
## Highlights
In this section, I want to highlight some of the LeptonX features.
### Better Mobile UX
When people talk about Responsive Web Applications, they usually refer to a side menu or top menu that shrinks down into a hamburger menu which does not provide a good user experience for mobile users.
On the other hand, widely used native mobile applications usually employ a tab menu stick to the bottom of the screen. People have become acquainted with this type of experience. With this UX in mind, menus in the `LeptonX` theme switches to the tab menu on the mobile resolution as opposed to the hamburger menu.
![Three iPhones showing LeptonX theme for mobile resolution in dark, dim, and light themes](./mobiles.png)
![Three iPads showing LeptonX theme for tablet resolution in dark, dim and light themes](./tablets.png)
### Theme Build System
Following the latest trends, LeptonX comes with three built-in theme styles; `dark`, `dim`, `light`.
A theme builder system (written in SASS) is provided with the LeptonX which you can run with your brand colors and create your own theme style as well.
LeptonX is built on top of CSS variables that enable runtime theme building. In the future, we may release a color picker that can create custom themes. Each user can create their own color palettes.
### Multiple Layouts
LeptonX is being developed with such an architecture that it will be easy to replace the layout. You will be given many options to choose any layout you prefer.
Take a look at the following layouts:
![An image showing default layout for LeptonX lite and pro packages](./default-layout.png)
![An image showing top menu layout](./top-menu-layout.png)
## The LeptonX Ecosystem
The previous version of Lepton Theme has been only available to Commercial ABP customers and it has never been as a standalone (ABP independent) template. With LeptonX, we aim at a broader audience. With this goal in mind, LeptonX can be integrated into any tech stack you'd prefer as well as the ABP Framework. That's why you'll be offered a variety of packages as follows:
- A template with HTML, VanillaJS, CSS (can be used as ABP independent)
- You can just download this like any other template and start developing your application.
- An angular library (can be used as ABP independent)
- An upgradeable angular package contains layouts, components, directives, and services for you to build any application you'd like. If you choose this option, you'll be able to stay up-to-date with LeptonX as we will continue to introduce new features.
- A standalone Angular template that contains code of the npm package above (can be used as ABP independent)
- You can also download an angular template that contains the library above. You can edit it as you see fit, however, it will be harder to integrate new features once they become available.
- Free ABP packages for all of the clients available, MVC, Blazor, and Angular that utilizes the lite packages
- Client-specific packages that employ LeptonX-lite for open-source ABP users.
- Commercial ABP packages for all of the clients available, MVC, Blazor, and Angular that utilizes Pro (full version) packages
- Client-specific packages that employ, provide and extend all of the features that LeptonX-Pro packages have.
As is seen above, the LeptonX ecosystem contains multiple projects that are designed for different kinds of users.
## The LeptonX-lite
As mentioned above, there will be a free-to-use version of LeptonX. It will contain most of the basic features and components that the pro version has. It will be also a one-line change to upgrade from the lite version to the pro (full) version. Here, some of the differences between the lite and pro versions:
- The mobile tab navigation bar shown above will be only available to pro. In the lite version, a hamburger menu will take its place.
- The lite version will be released just with the side menu layout although we may release more in the future as our infrastructure makes it easy to develop and replace layouts.
- Different color options and the ability to change colors during runtime are pro-only features. CSS of the lite version is built with the `dim` colors.
## Alpha Version
As we have mentioned above, both user and developer experience means a great deal to us. Therefore, we will release an alpha version of the LeptonX-lite package and the free ABP-based Angular package soon to start collecting feedback from our users. Once the packages are released, we would like you to try them out and give us feedback. It will help us improve the LeptonX greatly. We plan to release a stable version later this year.
To stay up-to-date with LeptonX and be notified once the alpha version is ready, follow our [Twitter account](https://twitter.com/volosoftcompany).

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

@ -59,9 +59,9 @@ Some specific types are registered to dependency injection by default. Examples:
* MVC controllers (inherit ``Controller`` or ``AbpController``) are registered as transient.
* MVC page models (inherit ``PageModel`` or ``AbpPageModel``) are registered as transient.
* MVC view components (inherit ``ViewComponent`` or ``AbpViewComponent``) are registered as transient.
* Application services (implement ``IApplicationService`` interface or inherit ``ApplicationService`` class) are registered as transient.
* Repositories (implement ``IRepository`` interface) are registered as transient.
* Domain services (implement ``IDomainService`` interface) are registered as transient.
* Application services (inherit ``ApplicationService`` class or its subclasses) are registered as transient.
* Repositories (implement ``BasicRepositoryBase`` class or its subclasses) are registered as transient.
* Domain services (implement ``IDomainService`` interface or inherit ``DomainService`` class) are registered as transient.
Example:

@ -1,12 +1,54 @@
# Account Module
This module provides necessary UI pages/components to make the user login and register to the application.
Account module implements the basic authentication features like **login**, **register**, **forgot password** and **account management**.
> This document is incomplete.
This module is based on [Microsoft's Identity library](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity) and the [Identity Module](Identity.md). It has [IdentityServer](https://github.com/IdentityServer) integration (based on the [IdentityServer Module](IdentityServer.md)) to provide **single sign-on**, access control and other advanced authentication features.
## How to Install
This module comes as pre-installed (as NuGet/NPM packages) when you [create a new solution](https://abp.io/get-started) with the ABP Framework. You can continue to use it as package and get updates easily, or you can include its source code into your solution (see `get-source` [CLI](../CLI.md) command) to develop your custom module.
### The Source Code
The source code of this module can be accessed [here](https://github.com/abpframework/abp/tree/dev/modules/account). The source code is licensed with [MIT](https://choosealicense.com/licenses/mit/), so you can freely use and customize it.
## User Interface
This section introduces the main pages provided by this module.
### Login
`/Account/Login` page provides the login functionality.
![account-module-login](../images/account-module-login.png)
Social/external login buttons becomes visible if you setup it. See the *Social/External Logins* section below. Register and Forgot password and links redirect to the pages explained in the next sections.
### Register
`/Account/Register` page provides the new user registration functionality.
![account-module-register](../images/account-module-register.png)
### Forgot Password & Reset Password
`/Account/ForgotPassword` page provides a way of sending password reset link to user's email address. The user then clicks to the link and determines a new password.
![account-module-forgot-password](../images/account-module-forgot-password.png)
### Account Management
`/Account/Manage` page is used to change password and personal information of the user.
![account-module-manage-account](../images/account-module-manage-account.png)
## IdentityServer Integration
[Volo.Abp.Account.Web.IdentityServer](https://www.nuget.org/packages/Volo.Abp.Account.Web.IdentityServer) package provides integration for the [IdentityServer](https://github.com/IdentityServer). This package comes as installed with the [application startup template](../Startup-Templates/Application.md). See the [IdentityServer Module](IdentityServer.md) documentation.
## Social/External Logins
The [Account Module](../Modules/Account.md) has already configured to handle social or external logins out of the box. You can follow the ASP.NET Core documentation to add a social/external login provider to your application.
The Account Module has already configured to handle social or external logins out of the box. You can follow the ASP.NET Core documentation to add a social/external login provider to your application.
### Example: Facebook Authentication
@ -32,7 +74,3 @@ context.Services.AddAuthentication()
````
> It would be a better practice to use the `appsettings.json` or the ASP.NET Core User Secrets system to store your credentials, instead of a hard-coded value like that. Follow the [Microsoft's document](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/facebook-logins) to learn the user secrets usage.
### Other UI Types
Beginning from the v3.1, the [Angular UI](../UI/Angular/Quick-Start.md) uses authorization code flow (as a best practice) to authenticate the user by redirecting to the MVC UI login page. So, even if you are using the Angular UI, social/external login integration is same as explained above and it will work out of the box. As similar, The [Blazor UI](../UI/Blazor/Overall.md) also uses the MVC UI to logic.

@ -1,38 +1,59 @@
# Identity Management Module
Identity module is used to manage organization units, roles, users and their permissions, based on the Microsoft Identity library.
Identity module is used to manage roles, users and their permissions, based on the [Microsoft Identity library](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity).
> **See [the source code](https://github.com/abpframework/abp/tree/dev/modules/identity). Documentation will come soon...**
## How to Install
This module comes as pre-installed (as NuGet/NPM packages) when you [create a new solution](https://abp.io/get-started) with the ABP Framework. You can continue to use it as package and get updates easily, or you can include its source code into your solution (see `get-source` [CLI](../CLI.md) command) to develop your custom module.
## Identity Security Log
### The Source Code
The security log can record some important operations or changes about your account. You can save the security log if needed.
The source code of this module can be accessed [here](https://github.com/abpframework/abp/tree/dev/modules/identity). The source code is licensed with [MIT](https://choosealicense.com/licenses/mit/), so you can freely use and customize it.
You can inject and use `IdentitySecurityLogManager` or `ISecurityLogManager` to write security logs. It will create a log object by default and fill in some common values, such as `CreationTime`, `ClientIpAddress`, `BrowserInfo`, `current user/tenant`, etc. Of course, you can override them.
## Menu Items
```cs
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = "IdentityServer";
Action = "ChangePassword";
});
```
This module adds an *Identity management* menu item under the *Administration* menu:
Configure `AbpSecurityLogOptions` to provide the application name for the log or disable this feature. **Enabled** by default.
![identity-module-menu](../images/identity-module-menu.png)
```cs
Configure<AbpSecurityLogOptions>(options =>
{
options.ApplicationName = "AbpSecurityTest";
});
```
The menu items and the related pages are authorized. That means the current user must have the related permissions to make them visible. The `admin` role (and the users with this role - like the `admin` user) already has these permissions. If you want to enable permissions for other roles/users, open the *Permissions* dialog on the *Roles* or *Users* page and check the permissions as shown below:
![identity-module-permissions](../images/identity-module-permissions.png)
See the [Authorization document](../Authorization.md) to understand the permission system.
## Pages
This section introduces the main pages provided by this module.
### Users
This page is used to see the list of users. You can create/edit and delete users, assign users to roles.
![identity-module-users](../images/identity-module-users.png)
A user can have zero or more roles. Users inherit permissions from their roles. In addition, you can assign permissions directly to the users (by clicking the *Actions* button, then selecting the *Permissions*).
### Roles
Roles are used to group permissions assign them to users.
![identity-module-roles](../images/identity-module-roles.png)
## Organization Unit Management
Beside the role name, there are two properties of a role:
Organization units (OU) is a part of **Identity Module** and can be used to **hierarchically group users and entities**.
* `Default`: If a role is marked as "default", then that role is assigned to new users by default when they register to the application themselves (using the [Account Module](Account.md)).
* `Public`: A public role of a user can be seen by other users in the application. This feature has no usage in the Identity module, but provided as a feature that you may want to use in your own application.
### OrganizationUnit Entity
## Other Features
This section covers some other features provided by this module which don't have the UI pages.
### Organization Units
Organization Units (OU) can be used to **hierarchically group users and entities**.
#### OrganizationUnit Entity
An OU is represented by the **OrganizationUnit** entity. The fundamental properties of this entity are:
@ -41,8 +62,6 @@ An OU is represented by the **OrganizationUnit** entity. The fundamental propert
- **Code**: A hierarchical string code that is unique for a tenant.
- **DisplayName**: Shown name of the OU.
The OrganizationUnit entity's primary key (Id) is a **Guid** type and it derives from the [**FullAuditedAggregateRoot**](../Entities.md) class.
#### Organization Tree
Since an OU can have a parent, all OUs of a tenant are in a **tree** structure. There are some rules for this tree;
@ -52,7 +71,7 @@ Since an OU can have a parent, all OUs of a tenant are in a **tree** structure.
#### OU Code
OU code is automatically generated and maintained by the OrganizationUnit Manager. It's a string that looks something like this:
OU code is automatically generated and maintained by the `OrganizationUnitManager` service. It's a string that looks something like this:
"**00001.00042.00005**"
@ -72,6 +91,29 @@ The **OrganizationUnitManager** class can be [injected](../Dependency-Injection.
- Move an OU in the OU tree.
- Getting information about the OU tree and its items.
#### Multi-Tenancy
### Identity Security Log
The security log can record some important operations or changes about your account. You can save the security log if needed.
You can inject and use `IdentitySecurityLogManager` or `ISecurityLogManager` to write security logs. It will create a log object by default and fill in some common values, such as `CreationTime`, `ClientIpAddress`, `BrowserInfo`, `current user/tenant`, etc. Of course, you can override them.
```cs
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = "IdentityServer";
Action = "ChangePassword";
});
```
Configure `AbpSecurityLogOptions` to provide the application name for the log or disable this feature. **Enabled** by default.
```cs
Configure<AbpSecurityLogOptions>(options =>
{
options.ApplicationName = "AbpSecurityTest";
});
```
### Options
The `OrganizationUnitManager` is designed to work for a **single tenant** at a time. It works for the **current tenant** by default.
TODO

@ -12,7 +12,7 @@ The [SaaS Module](https://commercial.abp.io/modules/Volo.Saas) is an alternative
## How to Install
This module comes as pre-installed (as [NuGet/NPM packages](NuGet/NPM packages)) when you [create a new solution](https://abp.io/get-started) with the ABP Framework. You can continue to use it as package and get updates easily, or you can include its source code into your solution (see `get-source` [CLI](../CLI.md) command) to develop your custom module.
This module comes as pre-installed (as NuGet/NPM packages) when you [create a new solution](https://abp.io/get-started) with the ABP Framework. You can continue to use it as package and get updates easily, or you can include its source code into your solution (see `get-source` [CLI](../CLI.md) command) to develop your custom module.
### The Source Code

@ -76,6 +76,9 @@ While there is no Razor Pages & MongoDB combination, you can check both document
* **DevExtreme MVC / Razor Pages Component Integration**: How to install and use DevExtreme components in the ABP Framework MVC / Razor Pages UI.
* [Source code](https://github.com/abpframework/abp-samples/tree/master/DevExtreme-Mvc)
* [Article](https://community.abp.io/articles/using-devextreme-components-with-the-abp-framework-zb8z7yqv)
* **Syncfusion Blazor Integration**: Shows how to install and integrate Syncfusion UI with ABP Framework Blazor UI.
* [Source code](https://github.com/abpframework/abp-samples/tree/master/SyncfusionSample)
* [Article](https://community.abp.io/articles/using-syncfusion-components-with-the-abp-framework-5ccvi8kc)
* **Empty ASP.NET Core Application**: The most basic ASP.NET Core application with the ABP Framework installed.
* [Source code](https://github.com/abpframework/abp-samples/tree/master/BasicAspNetCoreApplication)
* [Documentation](../Getting-Started-AspNetCore-Application.md)

@ -1,10 +1,10 @@
# Angular UI Account Module
Angular UI account module is available as of v4.3. It contains some pages (login, register, manage your profile, etc.).
Angular UI account module is available as of v4.3. It contains some pages (login, register, My account, etc.).
If you add the account module to your project;
- "Manage your profile" link in the current user dropdown on the top bar will redirect the user to a page in the account module.
- "My account" link in the current user dropdown on the top bar will redirect the user to a page in the account module.
- You can switch the authentication flow to the resource owner password flow.
@ -91,13 +91,13 @@ const routes: Routes = [
export class AppRoutingModule {}
```
### Manage Profile Page
### My Account Page
Before v4.3, the "Manage Your Profile" link in the current user dropdown on the top bar redirected the user to MVC's profile management page. As of v4.3, if you added the account module to your project, the same link will land on a page in the Angular UI account module instead.
Before v4.3, the "My account" link in the current user dropdown on the top bar redirected the user to MVC's profile management page. As of v4.3, if you added the account module to your project, the same link will land on a page in the Angular UI account module instead.
### My Security Logs Page [COMMERCIAL]
### Security Logs Page [COMMERCIAL]
Before v4.3, the "My Security Logs" link in the current user dropdown on the top bar redirected the user to MVC's my security logs page. As of v4.3, if you added the account module to your project, the same link will land on a page in the Angular UI account public module instead.
Before v4.3, the "Security Logs" link in the current user dropdown on the top bar redirected the user to MVC's security logs page. As of v4.3, if you added the account module to your project, the same link will land on a page in the Angular UI account public module instead.
### Resource Owner Password Flow

@ -491,7 +491,7 @@ Open the generated `nav-items.component.html` in `src/app/nav-items` folder and
[class.d-block]="smallScreen && currentUserDropdown.isOpen()"
>
<a class="dropdown-item pointer" (click)="navigateToManageProfile()"
><i class="fa fa-cog mr-1"></i>{%{{{ 'AbpAccount::ManageYourProfile' | abpLocalization }}}%}</a
><i class="fa fa-cog mr-1"></i>{%{{{ 'AbpAccount::MyAccount' | abpLocalization }}}%}</a
>
<a class="dropdown-item" href="javascript:void(0)" (click)="logout()"
><i class="fa fa-power-off mr-1"></i>{%{{{ 'AbpUi::Logout' | abpLocalization }}}%}</a

@ -83,8 +83,8 @@ See the [User Interface Customization Guide](Customization-User-Interface.md) to
### Copy & Customize
You can download the [source code](https://github.com/abpframework/abp/tree/dev/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic) of the Basic Theme, copy the project content into your solution, re-arrange the package/module dependencies (see the Installation section above to understand how it was installed to the project) and freely customize the theme based on your application requirements.
You can download the [source code](https://github.com/abpframework/abp/tree/rel-4.3/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic) of the Basic Theme, copy the project content into your solution, re-arrange the package/module dependencies (see the Installation section above to understand how it was installed to the project) and freely customize the theme based on your application requirements.
## See Also
* [Theming](Theming.md)
* [Theming](Theming.md)

@ -50,8 +50,8 @@ See the [Customization / Overriding Components](Customization-Overriding-Compone
### Copy & Customize
You can download the [source code](https://github.com/abpframework/abp/tree/dev/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme) of the Basic Theme, copy the project content into your solution, re-arrange the package/module dependencies (see the Installation section above to understand how it was installed to the project) and freely customize the theme based on your application requirements.
You can download the [source code](https://github.com/abpframework/abp/tree/rel-4.3/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme) of the Basic Theme, copy the project content into your solution, re-arrange the package/module dependencies (see the Installation section above to understand how it was installed to the project) and freely customize the theme based on your application requirements.
## See Also
* [Theming](Theming.md)
* [Theming](Theming.md)

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

@ -495,7 +495,7 @@ export class NavItemsComponent implements AfterViewInit {
[class.d-block]="smallScreen && currentUserDropdown.isOpen()"
>
<a class="dropdown-item" routerLink="/account/manage-profile"
><i class="fa fa-cog mr-1"></i>{%{{{ 'AbpAccount::ManageYourProfile' | abpLocalization }}}%}</a
><i class="fa fa-cog mr-1"></i>{%{{{ 'AbpAccount::MyAccount' | abpLocalization }}}%}</a
>
<a class="dropdown-item" href="javascript:void(0)" (click)="logout()"
><i class="fa fa-power-off mr-1"></i>{%{{{ 'AbpUi::Logout' | abpLocalization }}}%}</a

@ -11,12 +11,14 @@ namespace Microsoft.AspNetCore.Authentication.OAuth.Claims
{
claimActions.MapJsonKey(AbpClaimTypes.UserName, "name");
claimActions.DeleteClaim("name");
claimActions.RemoveDuplicate(AbpClaimTypes.UserName);
}
if (AbpClaimTypes.Email != "email")
{
claimActions.MapJsonKey(AbpClaimTypes.Email, "email");
claimActions.DeleteClaim("email");
claimActions.RemoveDuplicate(AbpClaimTypes.Email);
}
if (AbpClaimTypes.EmailVerified != "email_verified")
@ -38,11 +40,18 @@ namespace Microsoft.AspNetCore.Authentication.OAuth.Claims
{
claimActions.MapJsonKeyMultiple(AbpClaimTypes.Role, "role");
}
claimActions.RemoveDuplicate(AbpClaimTypes.Name);
}
public static void MapJsonKeyMultiple(this ClaimActionCollection claimActions, string claimType, string jsonKey)
{
claimActions.Add(new MultipleClaimAction(claimType, jsonKey));
}
public static void RemoveDuplicate(this ClaimActionCollection claimActions, string claimType)
{
claimActions.Add(new RemoveDuplicateClaimAction(claimType));
}
}
}

@ -1,4 +1,5 @@
using System.Security.Claims;
using System.Linq;
using System.Security.Claims;
using System.Text.Json;
using Microsoft.AspNetCore.Authentication.OAuth.Claims;
@ -24,15 +25,24 @@ namespace Volo.Abp.AspNetCore.Authentication.OAuth.Claims
return;
}
Claim claim;
switch (prop.ValueKind)
{
case JsonValueKind.String:
identity.AddClaim(new Claim(ClaimType, prop.GetString(), ValueType, issuer));
claim = new Claim(ClaimType, prop.GetString(), ValueType, issuer);
if (!identity.Claims.Any(c => c.Type == claim.Type && c.Value == claim.Value))
{
identity.AddClaim(claim);
}
break;
case JsonValueKind.Array:
foreach (var arramItem in prop.EnumerateArray())
{
identity.AddClaim(new Claim(ClaimType, arramItem.GetString(), ValueType, issuer));
claim = new Claim(ClaimType, arramItem.GetString(), ValueType, issuer);
if (!identity.Claims.Any(c => c.Type == claim.Type && c.Value == claim.Value))
{
identity.AddClaim(claim);
}
}
break;
default:

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text.Json;
using Microsoft.AspNetCore.Authentication.OAuth.Claims;
namespace Volo.Abp.AspNetCore.Authentication.OAuth.Claims
{
public class RemoveDuplicateClaimAction : ClaimAction
{
public RemoveDuplicateClaimAction(string claimType)
: base(claimType, ClaimValueTypes.String)
{
}
/// <inheritdoc />
public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer)
{
var claims = identity.Claims.Where(c => c.Type == ClaimType).ToArray();
if (claims.Length < 2)
{
return;
}
var previousValues = new List<string>();
foreach (var claim in claims)
{
if (claim.Value.IsIn(previousValues))
{
identity.RemoveClaim(claim);
}
else
{
previousValues.Add(claim.Value);
}
}
}
}
}

@ -157,10 +157,10 @@ namespace Volo.Abp.AspNetCore.Mvc
context.Services.TryAddSingleton<IActionContextAccessor, ActionContextAccessor>();
//Use DI to create controllers
context.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
mvcBuilder.AddControllersAsServices();
//Use DI to create view components
context.Services.Replace(ServiceDescriptor.Singleton<IViewComponentActivator, ServiceBasedViewComponentActivator>());
mvcBuilder.AddViewComponentsAsServices();
//Use DI to create razor page
context.Services.Replace(ServiceDescriptor.Singleton<IPageModelActivatorProvider, ServiceBasedPageModelActivatorProvider>());

@ -26,7 +26,7 @@ namespace Volo.Abp.Authorization.Permissions
return PermissionGrantResult.Undefined;
}
foreach (var role in roles)
foreach (var role in roles.Distinct())
{
if (await PermissionStore.IsGrantedAsync(context.Permission.Name, Name, role))
{
@ -50,7 +50,7 @@ namespace Volo.Abp.Authorization.Permissions
return result;
}
foreach (var role in roles)
foreach (var role in roles.Distinct())
{
var multipleResult = await PermissionStore.IsGrantedAsync(permissionNames.ToArray(), Name, role);

@ -10,6 +10,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building
var pipeline = new ProjectBuildPipeline(context);
pipeline.Steps.Add(new FileEntryListReadStep());
pipeline.Steps.Add(new CreateAppSettingsSecretsStep());
pipeline.Steps.Add(new ProjectReferenceReplaceStep());
pipeline.Steps.Add(new ReplaceCommonPropsStep());
pipeline.Steps.Add(new ReplaceConfigureAwaitPropsStep());

@ -0,0 +1,56 @@
using System;
using System.Linq;
using Volo.Abp.Cli.ProjectBuilding.Files;
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
public class CreateAppSettingsSecretsStep : ProjectBuildPipelineStep
{
private const string FileName = "appsettings.secrets.json";
private const string AppSettingsFileName = "appsettings.json";
private const string AppSettingsPlaceholder = "<!--APPSETTINGS-SECRETS-->";
public override void Execute(ProjectBuildContext context)
{
var appSettingsFiles = context.Files
.Where(x =>
x.Name.EndsWith(AppSettingsFileName) &&
NotBlazorWasmProject(x.Name))
.ToList();
var content = context.Template.IsPro()
? $"{{{Environment.NewLine} \"AbpLicenseCode\": \"<LICENSE_CODE/>\" {Environment.NewLine}}}"
: $"{{{Environment.NewLine}}}";
foreach (var appSettingsFile in appSettingsFiles)
{
context.Files.Add(new FileEntry(
appSettingsFile.Name.Replace(AppSettingsFileName, FileName),
content.GetBytes(),
false));
}
var projectFiles = context.Files.Where(x => x.Content.Contains(AppSettingsPlaceholder)).ToList();
foreach (var projectFile in projectFiles)
{
projectFile.SetContent(ReplaceAppSettingsSecretsPlaceholder(projectFile.Content));
}
}
private static bool NotBlazorWasmProject(string fileName)
{
return !fileName.Contains("Blazor/wwwroot") && !fileName.Contains("Blazor.Host/wwwroot");
}
private static string ReplaceAppSettingsSecretsPlaceholder(string content)
{
var replaceContent = $"<None Remove=\"{FileName}\" />{Environment.NewLine}" +
$" <Content Include=\"{FileName}\">{Environment.NewLine}" +
$" <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>{Environment.NewLine}" +
$" <CopyToOutputDirectory>Always</CopyToOutputDirectory>{Environment.NewLine}" +
" </Content>";
return content.Replace(AppSettingsPlaceholder, replaceContent);
}
}
}

@ -12,7 +12,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
var licenseCode = context.BuildArgs.ExtraProperties.GetOrDefault("license-code");
var appSettingsJsonFiles = context.Files.Where(f =>
f.Name.EndsWith("appsettings.json", StringComparison.OrdinalIgnoreCase));
f.Name.EndsWith("appsettings.json", StringComparison.OrdinalIgnoreCase) ||
f.Name.EndsWith("appsettings.secrets.json", StringComparison.OrdinalIgnoreCase));
foreach (var appSettingsJson in appSettingsJsonFiles)
{

@ -30,5 +30,10 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building
{
return Array.Empty<ProjectBuildPipelineStep>();
}
public bool IsPro()
{
return Name.EndsWith("pro", StringComparison.OrdinalIgnoreCase);
}
}
}

@ -12,6 +12,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building
var pipeline = new ProjectBuildPipeline(context);
pipeline.Steps.Add(new FileEntryListReadStep());
pipeline.Steps.Add(new CreateAppSettingsSecretsStep());
pipeline.Steps.AddRange(context.Template.GetCustomSteps(context));

@ -31,7 +31,7 @@ namespace Volo.Abp.Users
public virtual Guid? TenantId => _principalAccessor.Principal?.FindTenantId();
public virtual string[] Roles => FindClaims(AbpClaimTypes.Role).Select(c => c.Value).ToArray();
public virtual string[] Roles => FindClaims(AbpClaimTypes.Role).Select(c => c.Value).Distinct().ToArray();
private readonly ICurrentPrincipalAccessor _principalAccessor;

@ -7,10 +7,20 @@ namespace Volo.Abp.UI.Navigation
{
[NotNull]
public List<IMenuContributor> MenuContributors { get; }
/// <summary>
/// Includes the <see cref="StandardMenus.Main"/> by default.
/// </summary>
public List<string> MainMenuNames { get; }
public AbpNavigationOptions()
{
MenuContributors = new List<IMenuContributor>();
MainMenuNames = new List<string>
{
StandardMenus.Main
};
}
}
}

@ -5,5 +5,7 @@ namespace Volo.Abp.UI.Navigation
public interface IMenuManager
{
Task<ApplicationMenu> GetAsync(string name);
Task<ApplicationMenu> GetMainMenuAsync();
}
}

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
@ -24,7 +25,57 @@ namespace Volo.Abp.UI.Navigation
SimpleStateCheckerManager = simpleStateCheckerManager;
}
public async Task<ApplicationMenu> GetAsync(string name)
public Task<ApplicationMenu> GetAsync(string name)
{
return GetInternalAsync(name);
}
public Task<ApplicationMenu> GetMainMenuAsync()
{
return GetAsync(Options.MainMenuNames.ToArray());
}
protected virtual async Task<ApplicationMenu> GetAsync(params string[] menuNames)
{
if (menuNames.IsNullOrEmpty())
{
return new ApplicationMenu(StandardMenus.Main);
}
var menus = new List<ApplicationMenu>();
foreach (var menuName in Options.MainMenuNames)
{
menus.Add(await GetInternalAsync(menuName));
}
return MergeMenus(menus);
}
protected virtual ApplicationMenu MergeMenus(List<ApplicationMenu> menus)
{
Check.NotNullOrEmpty(menus, nameof(menus));
if (menus.Count == 1)
{
return menus[0];
}
var firstMenu = menus[0];
for (int i = 1; i < menus.Count; i++)
{
var currentMenu = menus[i];
foreach (var menuItem in currentMenu.Items)
{
firstMenu.AddItem(menuItem);
}
}
return firstMenu;
}
protected virtual async Task<ApplicationMenu> GetInternalAsync(string name)
{
var menu = new ApplicationMenu(name);

@ -15,6 +15,9 @@ namespace Volo.Abp.UI.Navigation
{
options.MenuContributors.Add(new MenuManager_Tests.TestMenuContributor1());
options.MenuContributors.Add(new MenuManager_Tests.TestMenuContributor2());
options.MenuContributors.Add(new MenuManager_Tests.TestMenuContributor3());
options.MainMenuNames.Add(MenuManager_Tests.TestMenuContributor3.MenuName);
});
}
}

@ -56,6 +56,19 @@ namespace Volo.Abp.UI.Navigation
// Administration.SubMenu1.1 and Administration.SubMenu1.2 are removed because of don't have permissions.
}
[Fact]
public async Task GetMainMenuAsync_ShouldMergeMultipleMenus()
{
var mainMenu = await _menuManager.GetMainMenuAsync();
mainMenu.Name.ShouldBe(StandardMenus.Main);
mainMenu.Items.Count.ShouldBe(3);
mainMenu.Items.ShouldContain(x => x.Name == "Products");
mainMenu.Items.ShouldContain(x => x.Name == "Dashboard");
}
/* Adds menu items:
* - Administration
* - User Management
@ -110,5 +123,31 @@ namespace Volo.Abp.UI.Navigation
return Task.CompletedTask;
}
}
/* Adds menu items:
* - Products
* - AspNetZero
* - ABP
*/
public class TestMenuContributor3 : IMenuContributor
{
public const string MenuName = "MenuThree";
public Task ConfigureMenuAsync(MenuConfigurationContext context)
{
if (context.Menu.Name != MenuName)
{
return Task.CompletedTask;
}
var products = new ApplicationMenuItem("Products", "Products", "/products");
context.Menu.Items.Add(products);
products.AddItem(new ApplicationMenuItem("AspNetZero", "AspNetZero", url: "/products/aspnetzero"));
products.AddItem(new ApplicationMenuItem("ABP", "ABP", url: "/products/abp"));
return Task.CompletedTask;
}
}
}
}

@ -36,7 +36,7 @@
"PasswordChanged": "تم تغيير كلمة المرور",
"NewPasswordConfirmFailed": "يرجى تأكيد كلمة المرور الجديدة.",
"Manage": "إدارة",
"ManageYourProfile": "إدارة ملف التعريف الخاص بك",
"MyAccount": "حسابي",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "هل تم تمكين التسجيل الذاتي",
"Description:Abp.Account.IsSelfRegistrationEnabled": "ما إذا كان يمكن للمستخدم تسجيل الحساب بنفسه أم لا.",
"DisplayName:Abp.Account.EnableLocalLogin": "المصادقة باستخدام حساب محلي",

@ -36,7 +36,7 @@
"PasswordChanged": "Heslo změněno",
"NewPasswordConfirmFailed": "Potvrďte nové heslo.",
"Manage": "Spravovat",
"ManageYourProfile": "Spravujte svůj profil",
"MyAccount": "Můj účet",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "Je povolena automatická registrace",
"Description:Abp.Account.IsSelfRegistrationEnabled": "Zda si uživatel může účet zaregistrovat sám.",
"DisplayName:Abp.Account.EnableLocalLogin": "Ověření pomocí místního účtu",

@ -36,7 +36,7 @@
"PasswordChanged": "Passwort geändert",
"NewPasswordConfirmFailed": "Bitte bestätigen Sie das neue Passwort.",
"Manage": "Verwalten",
"ManageYourProfile": "Verwalten Sie Ihr Profil",
"MyAccount": "Mein Benutzerkonto",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "Selbstregistrierung ist aktiviert",
"Description:Abp.Account.IsSelfRegistrationEnabled": "Gibt an, ob ein Benutzer das Benutzerkonto selbst registrieren kann.",
"DisplayName:Abp.Account.EnableLocalLogin": "Authentifizieren Sie sich mit einem lokalen Benutzerkonto",

@ -36,7 +36,7 @@
"PasswordChanged": "Passwort geändert",
"NewPasswordConfirmFailed": "Bitte bestätigen Sie das neue Passwort.",
"Manage": "Verwalten",
"ManageYourProfile": "Ihr Profil verwalten",
"MyAccount": "Mein Konto",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "Ist die Selbstregistrierung aktiviert",
"Description:Abp.Account.IsSelfRegistrationEnabled": "Gibt an, ob ein Benutzer das Konto selbst registrieren kann.",
"DisplayName:Abp.Account.EnableLocalLogin": "Authentifizierung mit einem lokalen Konto",

@ -36,7 +36,7 @@
"PasswordChanged": "Password changed",
"NewPasswordConfirmFailed": "Please confirm the new password.",
"Manage": "Manage",
"ManageYourProfile": "Manage your profile",
"MyAccount": "My account",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "Is self-registration enabled",
"Description:Abp.Account.IsSelfRegistrationEnabled": "Whether a user can register the account by his or her self.",
"DisplayName:Abp.Account.EnableLocalLogin": "Authenticate with a local account",

@ -36,7 +36,7 @@
"PasswordChanged": "Password changed",
"NewPasswordConfirmFailed": "Please confirm the new password.",
"Manage": "Manage",
"ManageYourProfile": "Manage your profile",
"MyAccount": "My account",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "Is self-registration enabled",
"Description:Abp.Account.IsSelfRegistrationEnabled": "Whether a user can register the account by him or herself.",
"DisplayName:Abp.Account.EnableLocalLogin": "Authenticate with a local account",

@ -33,6 +33,6 @@
"PasswordChanged": "Cambia la contraseña",
"NewPasswordConfirmFailed": "Por favor, confirme la nueva contraseña.",
"Manage": "Administrar",
"ManageYourProfile": "Gestionar tu perfil"
"MyAccount": "Mi cuenta"
}
}

@ -36,7 +36,7 @@
"PasswordChanged": "Cambiar la contraseña",
"NewPasswordConfirmFailed": "Por favor, confirme la nueva contraseña.",
"Manage": "Administrar",
"ManageYourProfile": "Administrar perfil",
"MyAccount": "Mi cuenta",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "¿El auto-registro está habilitado?",
"Description:Abp.Account.IsSelfRegistrationEnabled": "Cuando un usuario puede registrar la cuenta por él/ ella mismo/a",
"DisplayName:Abp.Account.EnableLocalLogin": "Autenticado con una cuenta local",

@ -36,7 +36,7 @@
"PasswordChanged": "Salasana vaihdettu",
"NewPasswordConfirmFailed": "Vahvista uusi salasana.",
"Manage": "Hallitse",
"ManageYourProfile": "Hallitse profiiliasi",
"MyAccount": "Tilini",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "Onko itserekisteröinti käytössä",
"Description:Abp.Account.IsSelfRegistrationEnabled": "Voiko käyttäjä rekisteröidä tilin itse.",
"DisplayName:Abp.Account.EnableLocalLogin": "Todennus paikallisella tilillä",

@ -36,7 +36,7 @@
"PasswordChanged": "Mot de passe changé",
"NewPasswordConfirmFailed": "Veuillez confirmer le nouveau mot de passe.",
"Manage": "Gérer",
"ManageYourProfile": "Gérez votre profil",
"MyAccount": "Mon compte",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "Lauto-inscription est-elle activée",
"Description:Abp.Account.IsSelfRegistrationEnabled": "Si un utilisateur peut enregistrer le compte par lui-même.",
"DisplayName:Abp.Account.EnableLocalLogin": "Authentifier avec un compte local",

@ -36,7 +36,7 @@
"PasswordChanged": "पासवर्ड बदला गया",
"NewPasswordConfirmFailed": "कृपया नए पासवर्ड की पुष्टि करें।",
"Manage": "प्रबंधित",
"ManageYourProfile": "अपनी प्रोफ़ाइल प्रबंधित करें",
"MyAccount": "मेरा खाता",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "क्या स्व-पंजीकरण सक्षम है",
"Description:Abp.Account.IsSelfRegistrationEnabled": "उपयोगकर्ता चाहे तो स्वयं या अपने द्वारा खाता पंजीकृत कर सकता है।",
"DisplayName:Abp.Account.EnableLocalLogin": "एक स्थानीय खाते के साथ प्रमाणीकरण",

@ -36,7 +36,7 @@
"PasswordChanged": "Jelszó megváltoztatva",
"NewPasswordConfirmFailed": "Kérjük, erősítse meg az új jelszót.",
"Manage": "Kezelés",
"ManageYourProfile": "Kezelje a profilját",
"MyAccount": "A fiókom",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "Engedélyezve van az önregisztráció",
"Description:Abp.Account.IsSelfRegistrationEnabled": "A felhasználó saját maga regisztrálhatja-e a fiókot.",
"DisplayName:Abp.Account.EnableLocalLogin": "Hitelesítés helyi fiókkal",

@ -36,7 +36,7 @@
"PasswordChanged": "Password cambiata",
"NewPasswordConfirmFailed": "Conferma la nuova password.",
"Manage": "Gestire",
"ManageYourProfile": "Gestisci il tuo profilo",
"MyAccount": "Il mio conto",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "L'auto-registrazione è abilitata",
"Description:Abp.Account.IsSelfRegistrationEnabled": "Se un utente può registrare l'account da solo.",
"DisplayName:Abp.Account.EnableLocalLogin": "Autentica con un account locale",

@ -36,7 +36,7 @@
"PasswordChanged": "Wachtwoord veranderd",
"NewPasswordConfirmFailed": "Bevestig het nieuwe wachtwoord a.u.b.",
"Manage": "Beheer",
"ManageYourProfile": "Beheer uw profiel",
"MyAccount": "Mijn rekening",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "Is zelfregistratie ingeschakeld",
"Description:Abp.Account.IsSelfRegistrationEnabled": "Of een gebruiker het account zelf kan registreren.",
"DisplayName:Abp.Account.EnableLocalLogin": "Verifieer met een lokaal account",

@ -35,6 +35,6 @@
"PasswordChanged": "Senha alterada",
"NewPasswordConfirmFailed": "Por favor, confirme a nova senha.",
"Manage": "Gerenciar",
"ManageYourProfile": "Gerenciar perfil"
"MyAccount": "Minha conta"
}
}

@ -36,7 +36,7 @@
"PasswordChanged": "Пароль изменен",
"NewPasswordConfirmFailed": "Пожалуйста подтвердите новый пароль.",
"Manage": "Управление учетной записью",
"ManageYourProfile": "Настройки",
"MyAccount": "Мой аккаунт",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "Самостоятельная регистрация включена",
"Description:Abp.Account.IsSelfRegistrationEnabled": "Позволяет новым пользователям регистрироваться самостоятельно.",
"DisplayName:Abp.Account.EnableLocalLogin": "Вход с помощью локальной учетной записи приложения",

@ -36,7 +36,7 @@
"PasswordChanged": "Geslo je spremenjeno",
"NewPasswordConfirmFailed": "Prosimo potrdite novo geslo.",
"Manage": "Upravljaj",
"ManageYourProfile": "Upravljaj svoj profil",
"MyAccount": "Moj račun",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "Je lastna registracija uporabnika omogočena",
"Description:Abp.Account.IsSelfRegistrationEnabled": "Ali lahko uporabnik sam registrira račun.",
"DisplayName:Abp.Account.EnableLocalLogin": "Avtenticirajte se z lokalnim računom",

@ -36,7 +36,7 @@
"PasswordChanged": "Şifre değiştirildi",
"NewPasswordConfirmFailed": "Lütfen yeni şifreyi onaylayın.",
"Manage": "Manage",
"ManageYourProfile": "Profilinizi yönetin",
"MyAccount": "Hesabım",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "self-registration etkin mi ?",
"Description:Abp.Account.IsSelfRegistrationEnabled": "Bir kullanıcının hesabı kendisi tarafından kaydedip kaydedememesidir.",
"DisplayName:Abp.Account.EnableLocalLogin": "Yerel bir hesapla kimlik doğrulaması",

@ -36,7 +36,7 @@
"PasswordChanged": "修改密码",
"NewPasswordConfirmFailed": "请确认新密码",
"Manage": "管理",
"ManageYourProfile": "管理你的个人资料",
"MyAccount": "我的账户",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "启用自行注册",
"Description:Abp.Account.IsSelfRegistrationEnabled": "是否允许用户自行注册帐户.",
"DisplayName:Abp.Account.EnableLocalLogin": "使用本地帐户进行身份验证",

@ -36,7 +36,7 @@
"PasswordChanged": "修改密碼",
"NewPasswordConfirmFailed": "請確認新密碼",
"Manage": "管理",
"ManageYourProfile": "管理你的個人資料",
"MyAccount": "我的賬戶",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "啟用自行註冊",
"Description:Abp.Account.IsSelfRegistrationEnabled": "是否允許使用者自行註冊帳號.",
"DisplayName:Abp.Account.EnableLocalLogin": "使用本地帳號進行身分驗證",

@ -15,7 +15,7 @@ namespace Volo.Abp.Account.Blazor
var accountResource = context.GetLocalizer<AccountResource>();
context.Menu.AddItem(new ApplicationMenuItem("Account.Manage", accountResource["ManageYourProfile"], url: "account/manage-profile", icon: "fa fa-cog"));
context.Menu.AddItem(new ApplicationMenuItem("Account.Manage", accountResource["MyAccount"], url: "account/manage-profile", icon: "fa fa-cog"));
return Task.CompletedTask;
}

@ -19,7 +19,7 @@ namespace Volo.Abp.Account.Web
var uiResource = context.GetLocalizer<AbpUiResource>();
var accountResource = context.GetLocalizer<AccountResource>();
context.Menu.AddItem(new ApplicationMenuItem("Account.Manage", accountResource["ManageYourProfile"], url: "~/Account/Manage", icon: "fa fa-cog", order: 1000, null));
context.Menu.AddItem(new ApplicationMenuItem("Account.Manage", accountResource["MyAccount"], url: "~/Account/Manage", icon: "fa fa-cog", order: 1000, null));
context.Menu.AddItem(new ApplicationMenuItem("Account.Logout", uiResource["Logout"], url: "~/Account/Logout", icon: "fa fa-power-off", order: int.MaxValue - 1000));
return Task.CompletedTask;

@ -13,7 +13,7 @@ namespace Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic
protected override async Task OnInitializedAsync()
{
Menu = await MenuManager.GetAsync(StandardMenus.Main);
Menu = await MenuManager.GetMainMenuAsync();
}
}
}

@ -15,7 +15,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Themes.Basic.Components.Menu
public async Task<IViewComponentResult> InvokeAsync()
{
var menu = await _menuManager.GetAsync(StandardMenus.Main);
var menu = await _menuManager.GetMainMenuAsync();
return View("~/Themes/Basic/Components/Menu/Default.cshtml", menu);
}
}

@ -1,6 +1,6 @@
{
"culture": "ar",
"texts": {
"ManageYourProfile": "إدارة ملف التعريف الخاص بك"
"MyAccount": "حسابي"
}
}

@ -1,6 +1,6 @@
{
"culture": "cs",
"texts": {
"ManageYourProfile": "Spravovat profil"
"MyAccount": "Můj účet"
}
}

@ -1,6 +1,6 @@
{
"culture": "de-DE",
"texts": {
"ManageYourProfile": "Verwalten Sie Ihr Profil"
"MyAccount": "Mein Konto"
}
}

@ -1,6 +1,6 @@
{
"culture": "en-GB",
"texts": {
"ManageYourProfile": "Manage your profile"
"MyAccount": "My account"
}
}

@ -1,6 +1,6 @@
{
"culture": "en",
"texts": {
"ManageYourProfile": "Manage your profile"
"MyAccount": "My account"
}
}

@ -1,6 +1,6 @@
{
"culture": "es",
"texts": {
"ManageYourProfile": "Administra tu perfil"
"MyAccount": "Mi cuenta"
}
}

@ -1,6 +1,6 @@
{
"culture": "fi",
"texts": {
"ManageYourProfile": "Hallitse profiiliasi"
"MyAccount": "Tilini"
}
}

@ -1,6 +1,6 @@
{
"culture": "fr",
"texts": {
"ManageYourProfile": "Gérer votre profil"
"MyAccount": "Mon compte"
}
}

@ -1,6 +1,6 @@
{
"culture": "hi",
"texts": {
"ManageYourProfile": "अपनी प्रोफ़ाइल प्रबंधित करें"
"MyAccount": "मेरा खाता"
}
}

@ -1,6 +1,6 @@
{
"culture": "hu",
"texts": {
"ManageYourProfile": "Kezelje a profilját"
"MyAccount": "A fiókom"
}
}

@ -1,6 +1,6 @@
{
"culture": "it",
"texts": {
"ManageYourProfile": "Gestisci il tuo profilo"
"MyAccount": "Il mio conto"
}
}

@ -1,6 +1,6 @@
{
"culture": "nl",
"texts": {
"ManageYourProfile": "Beheer uw profiel"
"MyAccount": "Mijn rekening"
}
}

@ -1,6 +1,6 @@
{
"culture": "sl",
"texts": {
"ManageYourProfile": "Upravljajte svojim profilom"
"MyAccount": "Moj račun"
}
}

@ -1,6 +1,6 @@
{
"culture": "tr",
"texts": {
"ManageYourProfile": "Profil yönetimi"
"MyAccount": "Hesabım"
}
}

@ -1,6 +1,6 @@
{
"culture": "zh-Hans",
"texts": {
"ManageYourProfile": "管理个人资料"
"MyAccount": "我的账户"
}
}

@ -1,6 +1,6 @@
{
"culture": "zh-Hant",
"texts": {
"ManageYourProfile": "管理個人資料"
"MyAccount": "我的賬戶"
}
}

@ -98,7 +98,7 @@ namespace Volo.BloggingTestApp
options.FileSets.ReplaceEmbeddedByPhysical<AbpAspNetCoreMvcUiModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI", Path.DirectorySeparatorChar)));
options.FileSets.ReplaceEmbeddedByPhysical<AbpAspNetCoreMvcUiBootstrapModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI.Bootstrap", Path.DirectorySeparatorChar)));
options.FileSets.ReplaceEmbeddedByPhysical<AbpAspNetCoreMvcUiThemeSharedModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared", Path.DirectorySeparatorChar)));
options.FileSets.ReplaceEmbeddedByPhysical<AbpAspNetCoreMvcUiBasicThemeModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic", Path.DirectorySeparatorChar)));
options.FileSets.ReplaceEmbeddedByPhysical<AbpAspNetCoreMvcUiBasicThemeModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}basic-theme{0}src{0}Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic", Path.DirectorySeparatorChar)));
options.FileSets.ReplaceEmbeddedByPhysical<BloggingDomainModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}Volo.Blogging.Domain", Path.DirectorySeparatorChar)));
options.FileSets.ReplaceEmbeddedByPhysical<BloggingWebModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}Volo.Blogging.Web", Path.DirectorySeparatorChar)));
});

@ -11,17 +11,17 @@ using Volo.CmsKit.EntityFrameworkCore;
namespace Volo.CmsKit.Migrations
{
[DbContext(typeof(CmsKitHttpApiHostMigrationsDbContext))]
[Migration("20201231111745_Initial")]
[Migration("20210609081519_Initial")]
partial class Initial
{
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.1");
.HasAnnotation("ProductVersion", "5.0.7")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Volo.Abp.BlobStoring.Database.DatabaseBlob", b =>
{
@ -96,6 +96,219 @@ namespace Volo.CmsKit.Migrations
b.ToTable("AbpBlobContainers");
});
modelBuilder.Entity("Volo.CmsKit.Blogs.Blog", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("Slug")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.ToTable("CmsBlogs");
});
modelBuilder.Entity("Volo.CmsKit.Blogs.BlogFeature", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid>("BlogId")
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<string>("FeatureName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<bool>("IsEnabled")
.HasColumnType("bit");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.HasKey("Id");
b.ToTable("CmsBlogFeatures");
});
modelBuilder.Entity("Volo.CmsKit.Blogs.BlogPost", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid>("AuthorId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("BlogId")
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<string>("Content")
.HasMaxLength(2147483647)
.HasColumnType("nvarchar(max)");
b.Property<Guid?>("CoverImageMediaId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("ShortDescription")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("Slug")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.HasIndex("Slug", "BlogId");
b.ToTable("CmsBlogPosts");
});
modelBuilder.Entity("Volo.CmsKit.Comments.Comment", b =>
{
b.Property<Guid>("Id")
@ -141,7 +354,7 @@ namespace Volo.CmsKit.Migrations
b.ToTable("CmsComments");
});
modelBuilder.Entity("Volo.CmsKit.Contents.Content", b =>
modelBuilder.Entity("Volo.CmsKit.MediaDescriptors.MediaDescriptor", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
@ -169,15 +382,79 @@ namespace Volo.CmsKit.Migrations
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("EntityId")
b.Property<string>("EntityType")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("EntityType")
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("MimeType")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("nvarchar(255)");
b.Property<long>("Size")
.HasMaxLength(2147483647)
.HasColumnType("bigint");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.ToTable("CmsMediaDescriptors");
});
modelBuilder.Entity("Volo.CmsKit.Menus.Menu", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
@ -197,20 +474,85 @@ namespace Volo.CmsKit.Migrations
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.HasColumnType("nvarchar(max)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<string>("Value")
b.HasKey("Id");
b.ToTable("CmsMenus");
});
modelBuilder.Entity("Volo.CmsKit.Menus.MenuItem", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<string>("CssClass")
.HasColumnType("nvarchar(max)");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(2147483647)
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("ElementId")
.HasColumnType("nvarchar(max)");
b.Property<string>("Icon")
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<Guid>("MenuId")
.HasColumnType("uniqueidentifier");
b.Property<int>("Order")
.HasColumnType("int");
b.Property<Guid?>("PageId")
.HasColumnType("uniqueidentifier");
b.Property<Guid?>("ParentId")
.HasColumnType("uniqueidentifier");
b.Property<string>("RequiredPermissionName")
.HasColumnType("nvarchar(max)");
b.Property<string>("Target")
.HasColumnType("nvarchar(max)");
b.Property<string>("Url")
.IsRequired()
.HasMaxLength(1024)
.HasColumnType("nvarchar(1024)");
b.HasKey("Id");
b.HasIndex("TenantId", "EntityType", "EntityId");
b.HasIndex("MenuId");
b.ToTable("CmsContents");
b.ToTable("CmsMenuItems");
});
modelBuilder.Entity("Volo.CmsKit.Pages.Page", b =>
@ -225,6 +567,10 @@ namespace Volo.CmsKit.Migrations
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<string>("Content")
.HasMaxLength(2147483647)
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
@ -241,10 +587,6 @@ namespace Volo.CmsKit.Migrations
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasMaxLength(512)
.HasColumnType("nvarchar(512)");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@ -263,23 +605,29 @@ namespace Volo.CmsKit.Migrations
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<string>("Script")
.HasColumnType("nvarchar(max)");
b.Property<string>("Title")
b.Property<string>("Slug")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("Url")
b.Property<string>("Style")
.HasColumnType("nvarchar(max)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("TenantId", "Url");
b.HasIndex("TenantId", "Slug");
b.ToTable("CmsPages");
});
@ -525,6 +873,31 @@ namespace Volo.CmsKit.Migrations
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Volo.CmsKit.Blogs.BlogPost", b =>
{
b.HasOne("Volo.CmsKit.Users.CmsUser", "Author")
.WithMany()
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Author");
});
modelBuilder.Entity("Volo.CmsKit.Menus.MenuItem", b =>
{
b.HasOne("Volo.CmsKit.Menus.Menu", null)
.WithMany("Items")
.HasForeignKey("MenuId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Volo.CmsKit.Menus.Menu", b =>
{
b.Navigation("Items");
});
#pragma warning restore 612, 618
}
}

@ -22,6 +22,52 @@ namespace Volo.CmsKit.Migrations
table.PrimaryKey("PK_AbpBlobContainers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "CmsBlogFeatures",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
BlogId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
FeatureName = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
IsEnabled = table.Column<bool>(type: "bit", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsBlogFeatures", x => x.Id);
});
migrationBuilder.CreateTable(
name: "CmsBlogs",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Name = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
Slug = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsBlogs", x => x.Id);
});
migrationBuilder.CreateTable(
name: "CmsComments",
columns: table => new
@ -41,14 +87,28 @@ namespace Volo.CmsKit.Migrations
});
migrationBuilder.CreateTable(
name: "CmsContents",
name: "CmsEntityTags",
columns: table => new
{
TagId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
EntityId = table.Column<string>(type: "nvarchar(450)", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsEntityTags", x => new { x.EntityId, x.TagId });
});
migrationBuilder.CreateTable(
name: "CmsMediaDescriptors",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
EntityType = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
EntityId = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
Value = table.Column<string>(type: "nvarchar(max)", maxLength: 2147483647, nullable: false),
Name = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false),
MimeType = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
Size = table.Column<long>(type: "bigint", maxLength: 2147483647, nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
@ -61,20 +121,29 @@ namespace Volo.CmsKit.Migrations
},
constraints: table =>
{
table.PrimaryKey("PK_CmsContents", x => x.Id);
table.PrimaryKey("PK_CmsMediaDescriptors", x => x.Id);
});
migrationBuilder.CreateTable(
name: "CmsEntityTags",
name: "CmsMenus",
columns: table => new
{
TagId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
EntityId = table.Column<string>(type: "nvarchar(450)", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Name = table.Column<string>(type: "nvarchar(max)", nullable: true),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsEntityTags", x => new { x.EntityId, x.TagId });
table.PrimaryKey("PK_CmsMenus", x => x.Id);
});
migrationBuilder.CreateTable(
@ -84,8 +153,10 @@ namespace Volo.CmsKit.Migrations
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Title = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Url = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Description = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
Slug = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Content = table.Column<string>(type: "nvarchar(max)", maxLength: 2147483647, nullable: true),
Script = table.Column<string>(type: "nvarchar(max)", nullable: true),
Style = table.Column<string>(type: "nvarchar(max)", nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
@ -123,9 +194,9 @@ namespace Volo.CmsKit.Migrations
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
EntityType = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
Name = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
@ -202,6 +273,73 @@ namespace Volo.CmsKit.Migrations
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "CmsMenuItems",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
MenuId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ParentId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DisplayName = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
IsActive = table.Column<bool>(type: "bit", nullable: false),
Url = table.Column<string>(type: "nvarchar(1024)", maxLength: 1024, nullable: false),
Icon = table.Column<string>(type: "nvarchar(max)", nullable: true),
Order = table.Column<int>(type: "int", nullable: false),
Target = table.Column<string>(type: "nvarchar(max)", nullable: true),
ElementId = table.Column<string>(type: "nvarchar(max)", nullable: true),
CssClass = table.Column<string>(type: "nvarchar(max)", nullable: true),
RequiredPermissionName = table.Column<string>(type: "nvarchar(max)", nullable: true),
PageId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsMenuItems", x => x.Id);
table.ForeignKey(
name: "FK_CmsMenuItems_CmsMenus_MenuId",
column: x => x.MenuId,
principalTable: "CmsMenus",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "CmsBlogPosts",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
BlogId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Title = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
Slug = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
ShortDescription = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
Content = table.Column<string>(type: "nvarchar(max)", maxLength: 2147483647, nullable: true),
CoverImageMediaId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
AuthorId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsBlogPosts", x => x.Id);
table.ForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_AuthorId",
column: x => x.AuthorId,
principalTable: "CmsUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_AbpBlobContainers_TenantId_Name",
table: "AbpBlobContainers",
@ -217,6 +355,16 @@ namespace Volo.CmsKit.Migrations
table: "AbpBlobs",
columns: new[] { "TenantId", "ContainerId", "Name" });
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_AuthorId",
table: "CmsBlogPosts",
column: "AuthorId");
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_Slug_BlogId",
table: "CmsBlogPosts",
columns: new[] { "Slug", "BlogId" });
migrationBuilder.CreateIndex(
name: "IX_CmsComments_TenantId_EntityType_EntityId",
table: "CmsComments",
@ -227,20 +375,20 @@ namespace Volo.CmsKit.Migrations
table: "CmsComments",
columns: new[] { "TenantId", "RepliedCommentId" });
migrationBuilder.CreateIndex(
name: "IX_CmsContents_TenantId_EntityType_EntityId",
table: "CmsContents",
columns: new[] { "TenantId", "EntityType", "EntityId" });
migrationBuilder.CreateIndex(
name: "IX_CmsEntityTags_TenantId_EntityId_TagId",
table: "CmsEntityTags",
columns: new[] { "TenantId", "EntityId", "TagId" });
migrationBuilder.CreateIndex(
name: "IX_CmsPages_TenantId_Url",
name: "IX_CmsMenuItems_MenuId",
table: "CmsMenuItems",
column: "MenuId");
migrationBuilder.CreateIndex(
name: "IX_CmsPages_TenantId_Slug",
table: "CmsPages",
columns: new[] { "TenantId", "Url" });
columns: new[] { "TenantId", "Slug" });
migrationBuilder.CreateIndex(
name: "IX_CmsRatings_TenantId_EntityType_EntityId_CreatorId",
@ -279,14 +427,26 @@ namespace Volo.CmsKit.Migrations
name: "AbpBlobs");
migrationBuilder.DropTable(
name: "CmsComments");
name: "CmsBlogFeatures");
migrationBuilder.DropTable(
name: "CmsBlogPosts");
migrationBuilder.DropTable(
name: "CmsBlogs");
migrationBuilder.DropTable(
name: "CmsContents");
name: "CmsComments");
migrationBuilder.DropTable(
name: "CmsEntityTags");
migrationBuilder.DropTable(
name: "CmsMediaDescriptors");
migrationBuilder.DropTable(
name: "CmsMenuItems");
migrationBuilder.DropTable(
name: "CmsPages");
@ -299,11 +459,14 @@ namespace Volo.CmsKit.Migrations
migrationBuilder.DropTable(
name: "CmsUserReactions");
migrationBuilder.DropTable(
name: "AbpBlobContainers");
migrationBuilder.DropTable(
name: "CmsUsers");
migrationBuilder.DropTable(
name: "AbpBlobContainers");
name: "CmsMenus");
}
}
}

@ -16,10 +16,10 @@ namespace Volo.CmsKit.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.UseIdentityColumns()
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("ProductVersion", "5.0.1");
.HasAnnotation("ProductVersion", "5.0.7")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Volo.Abp.BlobStoring.Database.DatabaseBlob", b =>
{
@ -94,6 +94,219 @@ namespace Volo.CmsKit.Migrations
b.ToTable("AbpBlobContainers");
});
modelBuilder.Entity("Volo.CmsKit.Blogs.Blog", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("Slug")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.ToTable("CmsBlogs");
});
modelBuilder.Entity("Volo.CmsKit.Blogs.BlogFeature", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid>("BlogId")
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<string>("FeatureName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<bool>("IsEnabled")
.HasColumnType("bit");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.HasKey("Id");
b.ToTable("CmsBlogFeatures");
});
modelBuilder.Entity("Volo.CmsKit.Blogs.BlogPost", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid>("AuthorId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("BlogId")
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<string>("Content")
.HasMaxLength(2147483647)
.HasColumnType("nvarchar(max)");
b.Property<Guid?>("CoverImageMediaId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("ShortDescription")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("Slug")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.HasIndex("Slug", "BlogId");
b.ToTable("CmsBlogPosts");
});
modelBuilder.Entity("Volo.CmsKit.Comments.Comment", b =>
{
b.Property<Guid>("Id")
@ -139,7 +352,7 @@ namespace Volo.CmsKit.Migrations
b.ToTable("CmsComments");
});
modelBuilder.Entity("Volo.CmsKit.Contents.Content", b =>
modelBuilder.Entity("Volo.CmsKit.MediaDescriptors.MediaDescriptor", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
@ -167,15 +380,79 @@ namespace Volo.CmsKit.Migrations
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("EntityId")
b.Property<string>("EntityType")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("EntityType")
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("MimeType")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("nvarchar(255)");
b.Property<long>("Size")
.HasMaxLength(2147483647)
.HasColumnType("bigint");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.ToTable("CmsMediaDescriptors");
});
modelBuilder.Entity("Volo.CmsKit.Menus.Menu", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
@ -195,20 +472,85 @@ namespace Volo.CmsKit.Migrations
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.HasColumnType("nvarchar(max)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<string>("Value")
b.HasKey("Id");
b.ToTable("CmsMenus");
});
modelBuilder.Entity("Volo.CmsKit.Menus.MenuItem", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<string>("CssClass")
.HasColumnType("nvarchar(max)");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(2147483647)
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("ElementId")
.HasColumnType("nvarchar(max)");
b.Property<string>("Icon")
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<Guid>("MenuId")
.HasColumnType("uniqueidentifier");
b.Property<int>("Order")
.HasColumnType("int");
b.Property<Guid?>("PageId")
.HasColumnType("uniqueidentifier");
b.Property<Guid?>("ParentId")
.HasColumnType("uniqueidentifier");
b.Property<string>("RequiredPermissionName")
.HasColumnType("nvarchar(max)");
b.Property<string>("Target")
.HasColumnType("nvarchar(max)");
b.Property<string>("Url")
.IsRequired()
.HasMaxLength(1024)
.HasColumnType("nvarchar(1024)");
b.HasKey("Id");
b.HasIndex("TenantId", "EntityType", "EntityId");
b.HasIndex("MenuId");
b.ToTable("CmsContents");
b.ToTable("CmsMenuItems");
});
modelBuilder.Entity("Volo.CmsKit.Pages.Page", b =>
@ -223,6 +565,10 @@ namespace Volo.CmsKit.Migrations
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<string>("Content")
.HasMaxLength(2147483647)
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
@ -239,10 +585,6 @@ namespace Volo.CmsKit.Migrations
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasMaxLength(512)
.HasColumnType("nvarchar(512)");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@ -261,23 +603,29 @@ namespace Volo.CmsKit.Migrations
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<string>("Script")
.HasColumnType("nvarchar(max)");
b.Property<string>("Title")
b.Property<string>("Slug")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("Url")
b.Property<string>("Style")
.HasColumnType("nvarchar(max)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("TenantId", "Url");
b.HasIndex("TenantId", "Slug");
b.ToTable("CmsPages");
});
@ -523,6 +871,31 @@ namespace Volo.CmsKit.Migrations
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Volo.CmsKit.Blogs.BlogPost", b =>
{
b.HasOne("Volo.CmsKit.Users.CmsUser", "Author")
.WithMany()
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Author");
});
modelBuilder.Entity("Volo.CmsKit.Menus.MenuItem", b =>
{
b.HasOne("Volo.CmsKit.Menus.Menu", null)
.WithMany("Items")
.HasForeignKey("MenuId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Volo.CmsKit.Menus.Menu", b =>
{
b.Navigation("Items");
});
#pragma warning restore 612, 618
}
}

@ -36,7 +36,7 @@ namespace Volo.CmsKit
context.Menu.Items.Add(new ApplicationMenuItem(
"Account.Manage",
l["ManageYourProfile"],
l["MyAccount"],
$"{_configuration["AuthServer:Authority"].EnsureEndsWith('/')}Account/Manage",
icon: "fa fa-cog",
order: int.MaxValue - 1001,

@ -1,23 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.CmsKit.Migrations
{
public partial class BlogFeatureEnabledColumnRename : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "Enabled",
table: "CmsBlogFeatures",
newName: "IsEnabled");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "IsEnabled",
table: "CmsBlogFeatures",
newName: "Enabled");
}
}
}

@ -1,24 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.CmsKit.Migrations
{
public partial class Page_Remove_Description : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Description",
table: "CmsPages");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Description",
table: "CmsPages",
type: "nvarchar(512)",
maxLength: 512,
nullable: true);
}
}
}

@ -1,109 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.CmsKit.Migrations
{
public partial class BlogPost_Author : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_CreatorId",
table: "CmsBlogPosts");
migrationBuilder.DropForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_DeleterId",
table: "CmsBlogPosts");
migrationBuilder.DropForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_LastModifierId",
table: "CmsBlogPosts");
migrationBuilder.DropIndex(
name: "IX_CmsBlogPosts_CreatorId",
table: "CmsBlogPosts");
migrationBuilder.DropIndex(
name: "IX_CmsBlogPosts_DeleterId",
table: "CmsBlogPosts");
migrationBuilder.DropIndex(
name: "IX_CmsBlogPosts_LastModifierId",
table: "CmsBlogPosts");
migrationBuilder.AddColumn<Guid>(
name: "AuthorId",
table: "CmsBlogPosts",
type: "uniqueidentifier",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_AuthorId",
table: "CmsBlogPosts",
column: "AuthorId");
migrationBuilder.AddForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_AuthorId",
table: "CmsBlogPosts",
column: "AuthorId",
principalTable: "CmsUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_AuthorId",
table: "CmsBlogPosts");
migrationBuilder.DropIndex(
name: "IX_CmsBlogPosts_AuthorId",
table: "CmsBlogPosts");
migrationBuilder.DropColumn(
name: "AuthorId",
table: "CmsBlogPosts");
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_CreatorId",
table: "CmsBlogPosts",
column: "CreatorId");
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_DeleterId",
table: "CmsBlogPosts",
column: "DeleterId");
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_LastModifierId",
table: "CmsBlogPosts",
column: "LastModifierId");
migrationBuilder.AddForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_CreatorId",
table: "CmsBlogPosts",
column: "CreatorId",
principalTable: "CmsUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
migrationBuilder.AddForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_DeleterId",
table: "CmsBlogPosts",
column: "DeleterId",
principalTable: "CmsUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
migrationBuilder.AddForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_LastModifierId",
table: "CmsBlogPosts",
column: "LastModifierId",
principalTable: "CmsUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
}
}
}

@ -1,25 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.CmsKit.Migrations
{
public partial class Added_EntityType_to_Media : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "EntityType",
table: "CmsMediaDescriptors",
type: "nvarchar(64)",
maxLength: 64,
nullable: false,
defaultValue: "");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "EntityType",
table: "CmsMediaDescriptors");
}
}
}

@ -1,24 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.CmsKit.Migrations
{
public partial class Added_Content_To_BlogPost : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Content",
table: "CmsBlogPosts",
type: "nvarchar(max)",
maxLength: 2147483647,
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Content",
table: "CmsBlogPosts");
}
}
}

@ -1,24 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.CmsKit.Migrations
{
public partial class Added_Content_To_Page : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Content",
table: "CmsPages",
type: "nvarchar(max)",
maxLength: 2147483647,
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Content",
table: "CmsPages");
}
}
}

@ -1,56 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.CmsKit.Migrations
{
public partial class BlogPost_CoverImage : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "CmsContents");
migrationBuilder.AddColumn<Guid>(
name: "CoverImageMediaId",
table: "CmsBlogPosts",
type: "uniqueidentifier",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "CoverImageMediaId",
table: "CmsBlogPosts");
migrationBuilder.CreateTable(
name: "CmsContents",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true),
EntityId = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
EntityType = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Value = table.Column<string>(type: "nvarchar(max)", maxLength: 2147483647, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsContents", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_CmsContents_TenantId_EntityType_EntityId",
table: "CmsContents",
columns: new[] { "TenantId", "EntityType", "EntityId" });
}
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save