From eb630372ba3d58d4de4e1b5c8da6ab0cfab092a4 Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Mon, 25 May 2020 11:04:01 +0800 Subject: [PATCH 01/20] Write error logs instead of throwing exceptions when Elasitc Search has errors Related #4042 --- .../FullSearch/Elastic/ElasticDocumentFullSearch.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/ElasticDocumentFullSearch.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/ElasticDocumentFullSearch.cs index 854032ab2c..cbe5905d3a 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/ElasticDocumentFullSearch.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/ElasticDocumentFullSearch.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Elasticsearch.Net; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Nest; using Volo.Abp; @@ -14,10 +15,14 @@ namespace Volo.Docs.Documents.FullSearch.Elastic { private readonly IElasticClientProvider _clientProvider; private readonly DocsElasticSearchOptions _options; + private readonly ILogger _logger; - public ElasticDocumentFullSearch(IElasticClientProvider clientProvider, IOptions options) + public ElasticDocumentFullSearch(IElasticClientProvider clientProvider, + IOptions options, + ILogger logger) { _clientProvider = clientProvider; + _logger = logger; _options = options.Value; } @@ -215,7 +220,8 @@ namespace Volo.Docs.Documents.FullSearch.Elastic { if (!response.ApiCall.Success) { - throw response.ApiCall.OriginalException; + _logger.LogError(response.ApiCall.OriginalException, + "An error occurred in the elastic search api call."); } } From 3451058a4d30aa1dd1aed3169bbdde125624d098 Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Mon, 25 May 2020 11:09:01 +0800 Subject: [PATCH 02/20] Make DbContextOptionsFactory public. Resolve #4066 --- .../DependencyInjection/DbContextOptionsFactory.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/DbContextOptionsFactory.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/DbContextOptionsFactory.cs index 00b73ff910..a2d52eac48 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/DbContextOptionsFactory.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/DbContextOptionsFactory.cs @@ -7,7 +7,7 @@ using Volo.Abp.Data; namespace Volo.Abp.EntityFrameworkCore.DependencyInjection { - internal static class DbContextOptionsFactory + public static class DbContextOptionsFactory { public static DbContextOptions Create(IServiceProvider serviceProvider) where TDbContext : AbpDbContext @@ -94,4 +94,4 @@ namespace Volo.Abp.EntityFrameworkCore.DependencyInjection ); } } -} \ No newline at end of file +} From cf2ded70719b9ecc8d23336dab7a2862f21e3c1b Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Mon, 25 May 2020 13:18:38 +0800 Subject: [PATCH 03/20] Recreate the migration of app template. --- ....cs => 20200525051739_Initial.Designer.cs} | 183 +++++++++++++++++- ...9_Initial.cs => 20200525051739_Initial.cs} | 113 +++++++++++ ...ectNameMigrationsDbContextModelSnapshot.cs | 181 ++++++++++++++++- 3 files changed, 474 insertions(+), 3 deletions(-) rename templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/{20200106080719_Initial.Designer.cs => 20200525051739_Initial.Designer.cs} (90%) rename templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/{20200106080719_Initial.cs => 20200525051739_Initial.cs} (90%) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/20200106080719_Initial.Designer.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/20200525051739_Initial.Designer.cs similarity index 90% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/20200106080719_Initial.Designer.cs rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/20200525051739_Initial.Designer.cs index 252d7d8c3d..c77694a007 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/20200106080719_Initial.Designer.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/20200525051739_Initial.Designer.cs @@ -10,14 +10,14 @@ using MyCompanyName.MyProjectName.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameMigrationsDbContext))] - [Migration("20200106080719_Initial")] + [Migration("20200525051739_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.0") + .HasAnnotation("ProductVersion", "3.1.2") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -58,6 +58,8 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") .HasColumnType("nvarchar(max)"); b.Property("CorrelationId") @@ -166,6 +168,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -259,6 +262,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -275,6 +279,8 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") .HasColumnType("nvarchar(max)"); b.Property("CreationTime") @@ -442,6 +448,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -469,6 +476,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -638,6 +646,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(1024); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("UserId") @@ -669,6 +678,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(196); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "LoginProvider"); @@ -678,6 +688,33 @@ namespace MyCompanyName.MyProjectName.Migrations b.ToTable("AbpUserLogins"); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.Property("UserId") @@ -687,6 +724,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "RoleId"); @@ -710,6 +748,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(128); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("Value") @@ -720,6 +759,106 @@ namespace MyCompanyName.MyProjectName.Migrations b.ToTable("AbpUserTokens"); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasColumnName("Code") + .HasColumnType("nvarchar(95)") + .HasMaxLength(95); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnName("DisplayName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles"); + }); + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b => { b.Property("Id") @@ -1275,6 +1414,8 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(200); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") .HasColumnType("nvarchar(max)"); b.Property("CreationTime") @@ -1427,6 +1568,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -1597,6 +1739,21 @@ namespace MyCompanyName.MyProjectName.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.HasOne("Volo.Abp.Identity.IdentityRole", null) @@ -1621,6 +1778,28 @@ namespace MyCompanyName.MyProjectName.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => { b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource", null) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/20200106080719_Initial.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/20200525051739_Initial.cs similarity index 90% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/20200106080719_Initial.cs rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/20200525051739_Initial.cs index 170372b3e0..03224bc2b9 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/20200106080719_Initial.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/20200525051739_Initial.cs @@ -95,6 +95,36 @@ namespace MyCompanyName.MyProjectName.Migrations table.PrimaryKey("PK_AbpFeatureValues", x => x.Id); }); + migrationBuilder.CreateTable( + name: "AbpOrganizationUnits", + columns: table => new + { + Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false, defaultValue: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), + TenantId = table.Column(nullable: true), + ParentId = table.Column(nullable: true), + Code = table.Column(maxLength: 95, nullable: false), + DisplayName = table.Column(maxLength: 128, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnits", x => x.Id); + table.ForeignKey( + name: "FK_AbpOrganizationUnits_AbpOrganizationUnits_ParentId", + column: x => x.ParentId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + migrationBuilder.CreateTable( name: "AbpPermissionGrants", columns: table => new @@ -402,6 +432,33 @@ namespace MyCompanyName.MyProjectName.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "AbpOrganizationUnitRoles", + columns: table => new + { + RoleId = table.Column(nullable: false), + OrganizationUnitId = table.Column(nullable: false), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnitRoles", x => new { x.OrganizationUnitId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "AbpRoleClaims", columns: table => new @@ -484,6 +541,33 @@ namespace MyCompanyName.MyProjectName.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "AbpUserOrganizationUnits", + columns: table => new + { + UserId = table.Column(nullable: false), + OrganizationUnitId = table.Column(nullable: false), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserOrganizationUnits", x => new { x.OrganizationUnitId, x.UserId }); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "AbpUserRoles", columns: table => new @@ -864,6 +948,21 @@ namespace MyCompanyName.MyProjectName.Migrations table: "AbpFeatureValues", columns: new[] { "Name", "ProviderName", "ProviderKey" }); + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", + table: "AbpOrganizationUnitRoles", + columns: new[] { "RoleId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_Code", + table: "AbpOrganizationUnits", + column: "Code"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_ParentId", + table: "AbpOrganizationUnits", + column: "ParentId"); + migrationBuilder.CreateIndex( name: "IX_AbpPermissionGrants_Name_ProviderName_ProviderKey", table: "AbpPermissionGrants", @@ -899,6 +998,11 @@ namespace MyCompanyName.MyProjectName.Migrations table: "AbpUserLogins", columns: new[] { "LoginProvider", "ProviderKey" }); + migrationBuilder.CreateIndex( + name: "IX_AbpUserOrganizationUnits_UserId_OrganizationUnitId", + table: "AbpUserOrganizationUnits", + columns: new[] { "UserId", "OrganizationUnitId" }); + migrationBuilder.CreateIndex( name: "IX_AbpUserRoles_RoleId_UserId", table: "AbpUserRoles", @@ -974,6 +1078,9 @@ namespace MyCompanyName.MyProjectName.Migrations migrationBuilder.DropTable( name: "AbpFeatureValues"); + migrationBuilder.DropTable( + name: "AbpOrganizationUnitRoles"); + migrationBuilder.DropTable( name: "AbpPermissionGrants"); @@ -992,6 +1099,9 @@ namespace MyCompanyName.MyProjectName.Migrations migrationBuilder.DropTable( name: "AbpUserLogins"); + migrationBuilder.DropTable( + name: "AbpUserOrganizationUnits"); + migrationBuilder.DropTable( name: "AbpUserRoles"); @@ -1049,6 +1159,9 @@ namespace MyCompanyName.MyProjectName.Migrations migrationBuilder.DropTable( name: "AbpTenants"); + migrationBuilder.DropTable( + name: "AbpOrganizationUnits"); + migrationBuilder.DropTable( name: "AbpRoles"); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/MyProjectNameMigrationsDbContextModelSnapshot.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/MyProjectNameMigrationsDbContextModelSnapshot.cs index 9b3096b4ba..d97218fba1 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/MyProjectNameMigrationsDbContextModelSnapshot.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/MyProjectNameMigrationsDbContextModelSnapshot.cs @@ -15,7 +15,7 @@ namespace MyCompanyName.MyProjectName.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.0") + .HasAnnotation("ProductVersion", "3.1.2") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -56,6 +56,8 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") .HasColumnType("nvarchar(max)"); b.Property("CorrelationId") @@ -164,6 +166,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -257,6 +260,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -273,6 +277,8 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") .HasColumnType("nvarchar(max)"); b.Property("CreationTime") @@ -440,6 +446,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -467,6 +474,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -636,6 +644,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(1024); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("UserId") @@ -667,6 +676,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(196); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "LoginProvider"); @@ -676,6 +686,33 @@ namespace MyCompanyName.MyProjectName.Migrations b.ToTable("AbpUserLogins"); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.Property("UserId") @@ -685,6 +722,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "RoleId"); @@ -708,6 +746,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(128); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("Value") @@ -718,6 +757,106 @@ namespace MyCompanyName.MyProjectName.Migrations b.ToTable("AbpUserTokens"); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasColumnName("Code") + .HasColumnType("nvarchar(95)") + .HasMaxLength(95); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnName("DisplayName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles"); + }); + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b => { b.Property("Id") @@ -1273,6 +1412,8 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(200); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") .HasColumnType("nvarchar(max)"); b.Property("CreationTime") @@ -1425,6 +1566,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -1595,6 +1737,21 @@ namespace MyCompanyName.MyProjectName.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.HasOne("Volo.Abp.Identity.IdentityRole", null) @@ -1619,6 +1776,28 @@ namespace MyCompanyName.MyProjectName.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => { b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource", null) From 5890927501a1a5ae815c90f40cbe7131bb46d828 Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Mon, 25 May 2020 13:27:12 +0800 Subject: [PATCH 04/20] Recreate the migration of module template. --- ....cs => 20200525052535_Initial.Designer.cs} | 181 +++++++++++++++++- ...8_Initial.cs => 20200525052535_Initial.cs} | 113 +++++++++++ ...verHostMigrationsDbContextModelSnapshot.cs | 179 ++++++++++++++++- ....cs => 20200525052704_Initial.Designer.cs} | 179 ++++++++++++++++- ...3_Initial.cs => 20200525052704_Initial.cs} | 113 +++++++++++ .../UnifiedDbContextModelSnapshot.cs | 177 ++++++++++++++++- 6 files changed, 936 insertions(+), 6 deletions(-) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/{20200106080828_Initial.Designer.cs => 20200525052535_Initial.Designer.cs} (89%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/{20200106080828_Initial.cs => 20200525052535_Initial.cs} (90%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/{20200106080643_Initial.Designer.cs => 20200525052704_Initial.Designer.cs} (82%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/{20200106080643_Initial.cs => 20200525052704_Initial.cs} (81%) diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20200106080828_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20200525052535_Initial.Designer.cs similarity index 89% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20200106080828_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20200525052535_Initial.Designer.cs index d3c4fe12b3..d638042c2b 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20200106080828_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20200525052535_Initial.Designer.cs @@ -10,14 +10,14 @@ using MyCompanyName.MyProjectName.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(IdentityServerHostMigrationsDbContext))] - [Migration("20200106080828_Initial")] + [Migration("20200525052535_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.0") + .HasAnnotation("ProductVersion", "3.1.2") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -58,6 +58,8 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") .HasColumnType("nvarchar(max)"); b.Property("CorrelationId") @@ -166,6 +168,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -259,6 +262,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -356,6 +360,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -383,6 +388,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -552,6 +558,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(1024); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("UserId") @@ -583,6 +590,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(196); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "LoginProvider"); @@ -592,6 +600,33 @@ namespace MyCompanyName.MyProjectName.Migrations b.ToTable("AbpUserLogins"); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.Property("UserId") @@ -601,6 +636,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "RoleId"); @@ -624,6 +660,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(128); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("Value") @@ -634,6 +671,106 @@ namespace MyCompanyName.MyProjectName.Migrations b.ToTable("AbpUserTokens"); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasColumnName("Code") + .HasColumnType("nvarchar(95)") + .HasMaxLength(95); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnName("DisplayName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles"); + }); + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b => { b.Property("Id") @@ -1189,6 +1326,8 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(200); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") .HasColumnType("nvarchar(max)"); b.Property("CreationTime") @@ -1341,6 +1480,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -1511,6 +1651,21 @@ namespace MyCompanyName.MyProjectName.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.HasOne("Volo.Abp.Identity.IdentityRole", null) @@ -1535,6 +1690,28 @@ namespace MyCompanyName.MyProjectName.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => { b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource", null) diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20200106080828_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20200525052535_Initial.cs similarity index 90% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20200106080828_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20200525052535_Initial.cs index 29cc3396eb..6269e6d3c8 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20200106080828_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20200525052535_Initial.cs @@ -59,6 +59,36 @@ namespace MyCompanyName.MyProjectName.Migrations table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); }); + migrationBuilder.CreateTable( + name: "AbpOrganizationUnits", + columns: table => new + { + Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false, defaultValue: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), + TenantId = table.Column(nullable: true), + ParentId = table.Column(nullable: true), + Code = table.Column(maxLength: 95, nullable: false), + DisplayName = table.Column(maxLength: 128, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnits", x => x.Id); + table.ForeignKey( + name: "FK_AbpOrganizationUnits_AbpOrganizationUnits_ParentId", + column: x => x.ParentId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + migrationBuilder.CreateTable( name: "AbpPermissionGrants", columns: table => new @@ -366,6 +396,33 @@ namespace MyCompanyName.MyProjectName.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "AbpOrganizationUnitRoles", + columns: table => new + { + RoleId = table.Column(nullable: false), + OrganizationUnitId = table.Column(nullable: false), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnitRoles", x => new { x.OrganizationUnitId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "AbpRoleClaims", columns: table => new @@ -448,6 +505,33 @@ namespace MyCompanyName.MyProjectName.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "AbpUserOrganizationUnits", + columns: table => new + { + UserId = table.Column(nullable: false), + OrganizationUnitId = table.Column(nullable: false), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserOrganizationUnits", x => new { x.OrganizationUnitId, x.UserId }); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "AbpUserRoles", columns: table => new @@ -818,6 +902,21 @@ namespace MyCompanyName.MyProjectName.Migrations table: "AbpEntityPropertyChanges", column: "EntityChangeId"); + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", + table: "AbpOrganizationUnitRoles", + columns: new[] { "RoleId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_Code", + table: "AbpOrganizationUnits", + column: "Code"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_ParentId", + table: "AbpOrganizationUnits", + column: "ParentId"); + migrationBuilder.CreateIndex( name: "IX_AbpPermissionGrants_Name_ProviderName_ProviderKey", table: "AbpPermissionGrants", @@ -853,6 +952,11 @@ namespace MyCompanyName.MyProjectName.Migrations table: "AbpUserLogins", columns: new[] { "LoginProvider", "ProviderKey" }); + migrationBuilder.CreateIndex( + name: "IX_AbpUserOrganizationUnits_UserId_OrganizationUnitId", + table: "AbpUserOrganizationUnits", + columns: new[] { "UserId", "OrganizationUnitId" }); + migrationBuilder.CreateIndex( name: "IX_AbpUserRoles_RoleId_UserId", table: "AbpUserRoles", @@ -922,6 +1026,9 @@ namespace MyCompanyName.MyProjectName.Migrations migrationBuilder.DropTable( name: "AbpEntityPropertyChanges"); + migrationBuilder.DropTable( + name: "AbpOrganizationUnitRoles"); + migrationBuilder.DropTable( name: "AbpPermissionGrants"); @@ -940,6 +1047,9 @@ namespace MyCompanyName.MyProjectName.Migrations migrationBuilder.DropTable( name: "AbpUserLogins"); + migrationBuilder.DropTable( + name: "AbpUserOrganizationUnits"); + migrationBuilder.DropTable( name: "AbpUserRoles"); @@ -997,6 +1107,9 @@ namespace MyCompanyName.MyProjectName.Migrations migrationBuilder.DropTable( name: "AbpTenants"); + migrationBuilder.DropTable( + name: "AbpOrganizationUnits"); + migrationBuilder.DropTable( name: "AbpRoles"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/IdentityServerHostMigrationsDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/IdentityServerHostMigrationsDbContextModelSnapshot.cs index 33aa2b4ded..7e182ee1a4 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/IdentityServerHostMigrationsDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/IdentityServerHostMigrationsDbContextModelSnapshot.cs @@ -15,7 +15,7 @@ namespace MyCompanyName.MyProjectName.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.0") + .HasAnnotation("ProductVersion", "3.1.2") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -56,6 +56,8 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") .HasColumnType("nvarchar(max)"); b.Property("CorrelationId") @@ -164,6 +166,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -257,6 +260,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -354,6 +358,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -381,6 +386,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -550,6 +556,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(1024); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("UserId") @@ -581,6 +588,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(196); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "LoginProvider"); @@ -590,6 +598,33 @@ namespace MyCompanyName.MyProjectName.Migrations b.ToTable("AbpUserLogins"); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.Property("UserId") @@ -599,6 +634,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "RoleId"); @@ -622,6 +658,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(128); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("Value") @@ -632,6 +669,106 @@ namespace MyCompanyName.MyProjectName.Migrations b.ToTable("AbpUserTokens"); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasColumnName("Code") + .HasColumnType("nvarchar(95)") + .HasMaxLength(95); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnName("DisplayName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles"); + }); + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b => { b.Property("Id") @@ -1187,6 +1324,8 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(200); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") .HasColumnType("nvarchar(max)"); b.Property("CreationTime") @@ -1339,6 +1478,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -1509,6 +1649,21 @@ namespace MyCompanyName.MyProjectName.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.HasOne("Volo.Abp.Identity.IdentityRole", null) @@ -1533,6 +1688,28 @@ namespace MyCompanyName.MyProjectName.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => { b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource", null) diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20200106080643_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20200525052704_Initial.Designer.cs similarity index 82% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20200106080643_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20200525052704_Initial.Designer.cs index 93e8a25a34..959380db0c 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20200106080643_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20200525052704_Initial.Designer.cs @@ -10,14 +10,14 @@ using MyCompanyName.MyProjectName.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(UnifiedDbContext))] - [Migration("20200106080643_Initial")] + [Migration("20200525052704_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.0") + .HasAnnotation("ProductVersion", "3.1.2") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -58,6 +58,8 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") .HasColumnType("nvarchar(max)"); b.Property("CorrelationId") @@ -166,6 +168,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -259,6 +262,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -356,6 +360,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -383,6 +388,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -552,6 +558,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(1024); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("UserId") @@ -583,6 +590,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(196); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "LoginProvider"); @@ -592,6 +600,33 @@ namespace MyCompanyName.MyProjectName.Migrations b.ToTable("AbpUserLogins"); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.Property("UserId") @@ -601,6 +636,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "RoleId"); @@ -624,6 +660,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(128); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("Value") @@ -634,6 +671,106 @@ namespace MyCompanyName.MyProjectName.Migrations b.ToTable("AbpUserTokens"); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasColumnName("Code") + .HasColumnType("nvarchar(95)") + .HasMaxLength(95); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnName("DisplayName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles"); + }); + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => { b.Property("Id") @@ -656,6 +793,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -826,6 +964,21 @@ namespace MyCompanyName.MyProjectName.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.HasOne("Volo.Abp.Identity.IdentityRole", null) @@ -850,6 +1003,28 @@ namespace MyCompanyName.MyProjectName.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => { b.HasOne("Volo.Abp.TenantManagement.Tenant", null) diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20200106080643_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20200525052704_Initial.cs similarity index 81% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20200106080643_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20200525052704_Initial.cs index 50aaa468b2..b3ce564cb1 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20200106080643_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20200525052704_Initial.cs @@ -59,6 +59,36 @@ namespace MyCompanyName.MyProjectName.Migrations table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); }); + migrationBuilder.CreateTable( + name: "AbpOrganizationUnits", + columns: table => new + { + Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false, defaultValue: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), + TenantId = table.Column(nullable: true), + ParentId = table.Column(nullable: true), + Code = table.Column(maxLength: 95, nullable: false), + DisplayName = table.Column(maxLength: 128, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnits", x => x.Id); + table.ForeignKey( + name: "FK_AbpOrganizationUnits_AbpOrganizationUnits_ParentId", + column: x => x.ParentId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + migrationBuilder.CreateTable( name: "AbpPermissionGrants", columns: table => new @@ -215,6 +245,33 @@ namespace MyCompanyName.MyProjectName.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "AbpOrganizationUnitRoles", + columns: table => new + { + RoleId = table.Column(nullable: false), + OrganizationUnitId = table.Column(nullable: false), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnitRoles", x => new { x.OrganizationUnitId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "AbpRoleClaims", columns: table => new @@ -297,6 +354,33 @@ namespace MyCompanyName.MyProjectName.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "AbpUserOrganizationUnits", + columns: table => new + { + UserId = table.Column(nullable: false), + OrganizationUnitId = table.Column(nullable: false), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserOrganizationUnits", x => new { x.OrganizationUnitId, x.UserId }); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "AbpUserRoles", columns: table => new @@ -401,6 +485,21 @@ namespace MyCompanyName.MyProjectName.Migrations table: "AbpEntityPropertyChanges", column: "EntityChangeId"); + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", + table: "AbpOrganizationUnitRoles", + columns: new[] { "RoleId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_Code", + table: "AbpOrganizationUnits", + column: "Code"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_ParentId", + table: "AbpOrganizationUnits", + column: "ParentId"); + migrationBuilder.CreateIndex( name: "IX_AbpPermissionGrants_Name_ProviderName_ProviderKey", table: "AbpPermissionGrants", @@ -436,6 +535,11 @@ namespace MyCompanyName.MyProjectName.Migrations table: "AbpUserLogins", columns: new[] { "LoginProvider", "ProviderKey" }); + migrationBuilder.CreateIndex( + name: "IX_AbpUserOrganizationUnits_UserId_OrganizationUnitId", + table: "AbpUserOrganizationUnits", + columns: new[] { "UserId", "OrganizationUnitId" }); + migrationBuilder.CreateIndex( name: "IX_AbpUserRoles_RoleId_UserId", table: "AbpUserRoles", @@ -473,6 +577,9 @@ namespace MyCompanyName.MyProjectName.Migrations migrationBuilder.DropTable( name: "AbpEntityPropertyChanges"); + migrationBuilder.DropTable( + name: "AbpOrganizationUnitRoles"); + migrationBuilder.DropTable( name: "AbpPermissionGrants"); @@ -491,6 +598,9 @@ namespace MyCompanyName.MyProjectName.Migrations migrationBuilder.DropTable( name: "AbpUserLogins"); + migrationBuilder.DropTable( + name: "AbpUserOrganizationUnits"); + migrationBuilder.DropTable( name: "AbpUserRoles"); @@ -503,6 +613,9 @@ namespace MyCompanyName.MyProjectName.Migrations migrationBuilder.DropTable( name: "AbpTenants"); + migrationBuilder.DropTable( + name: "AbpOrganizationUnits"); + migrationBuilder.DropTable( name: "AbpRoles"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs index 2f58731622..b0640cec6d 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs @@ -15,7 +15,7 @@ namespace MyCompanyName.MyProjectName.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.0") + .HasAnnotation("ProductVersion", "3.1.2") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -56,6 +56,8 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") .HasColumnType("nvarchar(max)"); b.Property("CorrelationId") @@ -164,6 +166,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -257,6 +260,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -354,6 +358,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(256); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -381,6 +386,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -550,6 +556,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(1024); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("UserId") @@ -581,6 +588,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(196); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "LoginProvider"); @@ -590,6 +598,33 @@ namespace MyCompanyName.MyProjectName.Migrations b.ToTable("AbpUserLogins"); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.Property("UserId") @@ -599,6 +634,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "RoleId"); @@ -622,6 +658,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(128); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("Value") @@ -632,6 +669,106 @@ namespace MyCompanyName.MyProjectName.Migrations b.ToTable("AbpUserTokens"); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasColumnName("Code") + .HasColumnType("nvarchar(95)") + .HasMaxLength(95); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnName("DisplayName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles"); + }); + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => { b.Property("Id") @@ -654,6 +791,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -824,6 +962,21 @@ namespace MyCompanyName.MyProjectName.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.HasOne("Volo.Abp.Identity.IdentityRole", null) @@ -848,6 +1001,28 @@ namespace MyCompanyName.MyProjectName.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => { b.HasOne("Volo.Abp.TenantManagement.Tenant", null) From 0a8def4a726ea0434048d1745a350413ed191737 Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Mon, 25 May 2020 13:32:42 +0800 Subject: [PATCH 05/20] added organization unit migration for blogging. --- ...053003_Added_OrganizationUnits.Designer.cs | 1090 +++++++++++++++++ .../20200525053003_Added_OrganizationUnits.cs | 127 ++ .../BloggingTestAppDbContextModelSnapshot.cs | 164 +++ 3 files changed, 1381 insertions(+) create mode 100644 modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20200525053003_Added_OrganizationUnits.Designer.cs create mode 100644 modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20200525053003_Added_OrganizationUnits.cs diff --git a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20200525053003_Added_OrganizationUnits.Designer.cs b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20200525053003_Added_OrganizationUnits.Designer.cs new file mode 100644 index 0000000000..2a61fc9f9b --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20200525053003_Added_OrganizationUnits.Designer.cs @@ -0,0 +1,1090 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.BloggingTestApp.EntityFrameworkCore; + +namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations +{ + [DbContext(typeof(BloggingTestAppDbContext))] + [Migration("20200525053003_Added_OrganizationUnits")] + partial class Added_OrganizationUnits + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.2") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("Description") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsStatic") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("Regex") + .HasColumnType("nvarchar(512)") + .HasMaxLength(512); + + b.Property("RegexDescription") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ValueType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDefault") + .HasColumnName("IsDefault") + .HasColumnType("bit"); + + b.Property("IsPublic") + .HasColumnName("IsPublic") + .HasColumnType("bit"); + + b.Property("IsStatic") + .HasColumnName("IsStatic") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("NormalizedName") + .IsRequired() + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(1024)") + .HasMaxLength(1024); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnName("AccessFailedCount") + .HasColumnType("int") + .HasDefaultValue(0); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasColumnName("Email") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnName("EmailConfirmed") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnName("LockoutEnabled") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnName("Name") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("NormalizedEmail") + .IsRequired() + .HasColumnName("NormalizedEmail") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .IsRequired() + .HasColumnName("NormalizedUserName") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("PasswordHash") + .HasColumnName("PasswordHash") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("PhoneNumber") + .HasColumnName("PhoneNumber") + .HasColumnType("nvarchar(16)") + .HasMaxLength(16); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnName("PhoneNumberConfirmed") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("SecurityStamp") + .IsRequired() + .HasColumnName("SecurityStamp") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("Surname") + .HasColumnName("Surname") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnName("TwoFactorEnabled") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("UserName") + .IsRequired() + .HasColumnName("UserName") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(1024)") + .HasMaxLength(1024); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ProviderKey") + .IsRequired() + .HasColumnType("nvarchar(196)") + .HasMaxLength(196); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("Name") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasColumnName("Code") + .HasColumnType("nvarchar(95)") + .HasMaxLength(95); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnName("DisplayName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles"); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ProviderKey") + .IsRequired() + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("ProviderName") + .IsRequired() + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpPermissionGrants"); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("ProviderName") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(2048)") + .HasMaxLength(2048); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpSettings"); + }); + + modelBuilder.Entity("Volo.Blogging.Blogs.Blog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasColumnName("Description") + .HasColumnType("nvarchar(1024)") + .HasMaxLength(1024); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasColumnName("Name") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("ShortName") + .IsRequired() + .HasColumnName("ShortName") + .HasColumnType("nvarchar(32)") + .HasMaxLength(32); + + b.HasKey("Id"); + + b.ToTable("BlgBlogs"); + }); + + modelBuilder.Entity("Volo.Blogging.Comments.Comment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("PostId") + .HasColumnName("PostId") + .HasColumnType("uniqueidentifier"); + + b.Property("RepliedCommentId") + .HasColumnName("RepliedCommentId") + .HasColumnType("uniqueidentifier"); + + b.Property("Text") + .IsRequired() + .HasColumnName("Text") + .HasColumnType("nvarchar(1024)") + .HasMaxLength(1024); + + b.HasKey("Id"); + + b.HasIndex("PostId"); + + b.HasIndex("RepliedCommentId"); + + b.ToTable("BlgComments"); + }); + + modelBuilder.Entity("Volo.Blogging.Posts.Post", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("BlogId") + .HasColumnName("BlogId") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("Content") + .HasColumnName("Content") + .HasColumnType("nvarchar(max)") + .HasMaxLength(1048576); + + b.Property("CoverImage") + .IsRequired() + .HasColumnName("CoverImage") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasColumnName("Description") + .HasColumnType("nvarchar(1000)") + .HasMaxLength(1000); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("ReadCount") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasColumnName("Title") + .HasColumnType("nvarchar(512)") + .HasMaxLength(512); + + b.Property("Url") + .IsRequired() + .HasColumnName("Url") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.HasKey("Id"); + + b.HasIndex("BlogId"); + + b.ToTable("BlgPosts"); + }); + + modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b => + { + b.Property("PostId") + .HasColumnName("PostId") + .HasColumnType("uniqueidentifier"); + + b.Property("TagId") + .HasColumnName("TagId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("PostId", "TagId"); + + b.HasIndex("TagId"); + + b.ToTable("BlgPostTags"); + }); + + modelBuilder.Entity("Volo.Blogging.Tagging.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("BlogId") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasColumnName("Description") + .HasColumnType("nvarchar(512)") + .HasMaxLength(512); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasColumnName("Name") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("UsageCount") + .HasColumnName("UsageCount") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("BlgTags"); + }); + + modelBuilder.Entity("Volo.Blogging.Users.BlogUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .IsRequired() + .HasColumnName("Email") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnName("EmailConfirmed") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasColumnName("Name") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("PhoneNumber") + .HasColumnName("PhoneNumber") + .HasColumnType("nvarchar(16)") + .HasMaxLength(16); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnName("PhoneNumberConfirmed") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("Surname") + .HasColumnName("Surname") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserName") + .IsRequired() + .HasColumnName("UserName") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.ToTable("BlgUsers"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Blogging.Comments.Comment", b => + { + b.HasOne("Volo.Blogging.Posts.Post", null) + .WithMany() + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Blogging.Comments.Comment", null) + .WithMany() + .HasForeignKey("RepliedCommentId"); + }); + + modelBuilder.Entity("Volo.Blogging.Posts.Post", b => + { + b.HasOne("Volo.Blogging.Blogs.Blog", null) + .WithMany() + .HasForeignKey("BlogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b => + { + b.HasOne("Volo.Blogging.Posts.Post", null) + .WithMany("Tags") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Blogging.Tagging.Tag", null) + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20200525053003_Added_OrganizationUnits.cs b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20200525053003_Added_OrganizationUnits.cs new file mode 100644 index 0000000000..38ec0e5542 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20200525053003_Added_OrganizationUnits.cs @@ -0,0 +1,127 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations +{ + public partial class Added_OrganizationUnits : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpOrganizationUnits", + columns: table => new + { + Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false, defaultValue: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), + TenantId = table.Column(nullable: true), + ParentId = table.Column(nullable: true), + Code = table.Column(maxLength: 95, nullable: false), + DisplayName = table.Column(maxLength: 128, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnits", x => x.Id); + table.ForeignKey( + name: "FK_AbpOrganizationUnits_AbpOrganizationUnits_ParentId", + column: x => x.ParentId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnitRoles", + columns: table => new + { + RoleId = table.Column(nullable: false), + OrganizationUnitId = table.Column(nullable: false), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnitRoles", x => new { x.OrganizationUnitId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserOrganizationUnits", + columns: table => new + { + UserId = table.Column(nullable: false), + OrganizationUnitId = table.Column(nullable: false), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserOrganizationUnits", x => new { x.OrganizationUnitId, x.UserId }); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", + table: "AbpOrganizationUnitRoles", + columns: new[] { "RoleId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_Code", + table: "AbpOrganizationUnits", + column: "Code"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_ParentId", + table: "AbpOrganizationUnits", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserOrganizationUnits_UserId_OrganizationUnitId", + table: "AbpUserOrganizationUnits", + columns: new[] { "UserId", "OrganizationUnitId" }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpOrganizationUnitRoles"); + + migrationBuilder.DropTable( + name: "AbpUserOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnits"); + } + } +} diff --git a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs index 2b0641a680..00e9389e8f 100644 --- a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs +++ b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs @@ -347,6 +347,33 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.ToTable("AbpUserLogins"); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.Property("UserId") @@ -391,6 +418,106 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.ToTable("AbpUserTokens"); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasColumnName("Code") + .HasColumnType("nvarchar(95)") + .HasMaxLength(95); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnName("DisplayName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles"); + }); + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => { b.Property("Id") @@ -858,6 +985,21 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.HasOne("Volo.Abp.Identity.IdentityRole", null) @@ -882,6 +1024,28 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Blogging.Comments.Comment", b => { b.HasOne("Volo.Blogging.Posts.Post", null) From b7baa4639133b1ef6ccf1cbe3b87fcffc1e7cd5d Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Mon, 25 May 2020 13:34:34 +0800 Subject: [PATCH 06/20] added organization unit migration for Docs. --- ...ner.cs => 20200525053411_init.Designer.cs} | 175 +++++++++++++++++- ...2050853_init.cs => 20200525053411_init.cs} | 113 +++++++++++ .../VoloDocsDbContextModelSnapshot.cs | 173 ++++++++++++++++- 3 files changed, 458 insertions(+), 3 deletions(-) rename modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/{20200312050853_init.Designer.cs => 20200525053411_init.Designer.cs} (78%) rename modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/{20200312050853_init.cs => 20200525053411_init.cs} (76%) diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200312050853_init.Designer.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200525053411_init.Designer.cs similarity index 78% rename from modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200312050853_init.Designer.cs rename to modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200525053411_init.Designer.cs index 0309e4cbc4..2de428f388 100644 --- a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200312050853_init.Designer.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200525053411_init.Designer.cs @@ -10,14 +10,14 @@ using VoloDocs.EntityFrameworkCore; namespace VoloDocs.EntityFrameworkCore.Migrations { [DbContext(typeof(VoloDocsDbContext))] - [Migration("20200312050853_init")] + [Migration("20200525053411_init")] partial class init { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.1") + .HasAnnotation("ProductVersion", "3.1.2") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -109,6 +109,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .HasMaxLength(256); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -136,6 +137,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -305,6 +307,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .HasMaxLength(1024); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("UserId") @@ -336,6 +339,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .HasMaxLength(196); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "LoginProvider"); @@ -345,6 +349,33 @@ namespace VoloDocs.EntityFrameworkCore.Migrations b.ToTable("AbpUserLogins"); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.Property("UserId") @@ -354,6 +385,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "RoleId"); @@ -377,6 +409,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .HasMaxLength(128); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("Value") @@ -387,6 +420,106 @@ namespace VoloDocs.EntityFrameworkCore.Migrations b.ToTable("AbpUserTokens"); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasColumnName("Code") + .HasColumnType("nvarchar(95)") + .HasMaxLength(95); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnName("DisplayName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles"); + }); + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => { b.Property("Id") @@ -409,6 +542,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .HasMaxLength(64); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -635,6 +769,21 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.HasOne("Volo.Abp.Identity.IdentityRole", null) @@ -659,6 +808,28 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Docs.Documents.DocumentContributor", b => { b.HasOne("Volo.Docs.Documents.Document", null) diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200312050853_init.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200525053411_init.cs similarity index 76% rename from modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200312050853_init.cs rename to modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200525053411_init.cs index 938fbc6a1b..00854e6745 100644 --- a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200312050853_init.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200525053411_init.cs @@ -27,6 +27,36 @@ namespace VoloDocs.EntityFrameworkCore.Migrations table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); }); + migrationBuilder.CreateTable( + name: "AbpOrganizationUnits", + columns: table => new + { + Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false, defaultValue: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), + TenantId = table.Column(nullable: true), + ParentId = table.Column(nullable: true), + Code = table.Column(maxLength: 95, nullable: false), + DisplayName = table.Column(maxLength: 128, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnits", x => x.Id); + table.ForeignKey( + name: "FK_AbpOrganizationUnits_AbpOrganizationUnits_ParentId", + column: x => x.ParentId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + migrationBuilder.CreateTable( name: "AbpPermissionGrants", columns: table => new @@ -163,6 +193,33 @@ namespace VoloDocs.EntityFrameworkCore.Migrations table.PrimaryKey("PK_DocsProjects", x => x.Id); }); + migrationBuilder.CreateTable( + name: "AbpOrganizationUnitRoles", + columns: table => new + { + RoleId = table.Column(nullable: false), + OrganizationUnitId = table.Column(nullable: false), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnitRoles", x => new { x.OrganizationUnitId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "AbpRoleClaims", columns: table => new @@ -226,6 +283,33 @@ namespace VoloDocs.EntityFrameworkCore.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "AbpUserOrganizationUnits", + columns: table => new + { + UserId = table.Column(nullable: false), + OrganizationUnitId = table.Column(nullable: false), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserOrganizationUnits", x => new { x.OrganizationUnitId, x.UserId }); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "AbpUserRoles", columns: table => new @@ -292,6 +376,21 @@ namespace VoloDocs.EntityFrameworkCore.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", + table: "AbpOrganizationUnitRoles", + columns: new[] { "RoleId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_Code", + table: "AbpOrganizationUnits", + column: "Code"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_ParentId", + table: "AbpOrganizationUnits", + column: "ParentId"); + migrationBuilder.CreateIndex( name: "IX_AbpPermissionGrants_Name_ProviderName_ProviderKey", table: "AbpPermissionGrants", @@ -322,6 +421,11 @@ namespace VoloDocs.EntityFrameworkCore.Migrations table: "AbpUserLogins", columns: new[] { "LoginProvider", "ProviderKey" }); + migrationBuilder.CreateIndex( + name: "IX_AbpUserOrganizationUnits_UserId_OrganizationUnitId", + table: "AbpUserOrganizationUnits", + columns: new[] { "UserId", "OrganizationUnitId" }); + migrationBuilder.CreateIndex( name: "IX_AbpUserRoles_RoleId_UserId", table: "AbpUserRoles", @@ -353,6 +457,9 @@ namespace VoloDocs.EntityFrameworkCore.Migrations migrationBuilder.DropTable( name: "AbpClaimTypes"); + migrationBuilder.DropTable( + name: "AbpOrganizationUnitRoles"); + migrationBuilder.DropTable( name: "AbpPermissionGrants"); @@ -368,6 +475,9 @@ namespace VoloDocs.EntityFrameworkCore.Migrations migrationBuilder.DropTable( name: "AbpUserLogins"); + migrationBuilder.DropTable( + name: "AbpUserOrganizationUnits"); + migrationBuilder.DropTable( name: "AbpUserRoles"); @@ -380,6 +490,9 @@ namespace VoloDocs.EntityFrameworkCore.Migrations migrationBuilder.DropTable( name: "DocsProjects"); + migrationBuilder.DropTable( + name: "AbpOrganizationUnits"); + migrationBuilder.DropTable( name: "AbpRoles"); diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs index 165f0428cc..216a9a06f4 100644 --- a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs @@ -15,7 +15,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.1") + .HasAnnotation("ProductVersion", "3.1.2") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -107,6 +107,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .HasMaxLength(256); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -134,6 +135,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -303,6 +305,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .HasMaxLength(1024); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("UserId") @@ -334,6 +337,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .HasMaxLength(196); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "LoginProvider"); @@ -343,6 +347,33 @@ namespace VoloDocs.EntityFrameworkCore.Migrations b.ToTable("AbpUserLogins"); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.Property("UserId") @@ -352,6 +383,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "RoleId"); @@ -375,6 +407,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .HasMaxLength(128); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("Value") @@ -385,6 +418,106 @@ namespace VoloDocs.EntityFrameworkCore.Migrations b.ToTable("AbpUserTokens"); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasColumnName("Code") + .HasColumnType("nvarchar(95)") + .HasMaxLength(95); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnName("DisplayName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles"); + }); + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => { b.Property("Id") @@ -407,6 +540,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .HasMaxLength(64); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -633,6 +767,21 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.HasOne("Volo.Abp.Identity.IdentityRole", null) @@ -657,6 +806,28 @@ namespace VoloDocs.EntityFrameworkCore.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Docs.Documents.DocumentContributor", b => { b.HasOne("Volo.Docs.Documents.Document", null) From 2244cf30373723c1ab63a2b960e9916382d9b2c2 Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Mon, 25 May 2020 13:36:43 +0800 Subject: [PATCH 07/20] added organization unit migration for \MicroserviceDemo. --- ...053551_Added_OrganizationUnits.Designer.cs | 1883 +++++++++++++++++ .../20200525053551_Added_OrganizationUnits.cs | 127 ++ .../AuthServerDbContextModelSnapshot.cs | 179 +- 3 files changed, 2188 insertions(+), 1 deletion(-) create mode 100644 samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20200525053551_Added_OrganizationUnits.Designer.cs create mode 100644 samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20200525053551_Added_OrganizationUnits.cs diff --git a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20200525053551_Added_OrganizationUnits.Designer.cs b/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20200525053551_Added_OrganizationUnits.Designer.cs new file mode 100644 index 0000000000..e9da56b3b2 --- /dev/null +++ b/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20200525053551_Added_OrganizationUnits.Designer.cs @@ -0,0 +1,1883 @@ +// +using System; +using AuthServer.Host.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace AuthServer.Host.Migrations +{ + [DbContext(typeof(AuthServerDbContext))] + [Migration("20200525053551_Added_OrganizationUnits")] + partial class Added_OrganizationUnits + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.2") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ApplicationName") + .HasColumnName("ApplicationName") + .HasColumnType("nvarchar(96)") + .HasMaxLength(96); + + b.Property("BrowserInfo") + .HasColumnName("BrowserInfo") + .HasColumnType("nvarchar(512)") + .HasMaxLength(512); + + b.Property("ClientId") + .HasColumnName("ClientId") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("ClientIpAddress") + .HasColumnName("ClientIpAddress") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("ClientName") + .HasColumnName("ClientName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("Comments") + .HasColumnName("Comments") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CorrelationId") + .HasColumnName("CorrelationId") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("Exceptions") + .HasColumnName("Exceptions") + .HasColumnType("nvarchar(4000)") + .HasMaxLength(4000); + + b.Property("ExecutionDuration") + .HasColumnName("ExecutionDuration") + .HasColumnType("int"); + + b.Property("ExecutionTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("HttpMethod") + .HasColumnName("HttpMethod") + .HasColumnType("nvarchar(16)") + .HasMaxLength(16); + + b.Property("HttpStatusCode") + .HasColumnName("HttpStatusCode") + .HasColumnType("int"); + + b.Property("ImpersonatorTenantId") + .HasColumnName("ImpersonatorTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("ImpersonatorUserId") + .HasColumnName("ImpersonatorUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantName") + .HasColumnType("nvarchar(max)"); + + b.Property("Url") + .HasColumnName("Url") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("UserId") + .HasColumnName("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserName") + .HasColumnName("UserName") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ExecutionTime"); + + b.HasIndex("TenantId", "UserId", "ExecutionTime"); + + b.ToTable("AbpAuditLogs"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AuditLogId") + .HasColumnName("AuditLogId") + .HasColumnType("uniqueidentifier"); + + b.Property("ExecutionDuration") + .HasColumnName("ExecutionDuration") + .HasColumnType("int"); + + b.Property("ExecutionTime") + .HasColumnName("ExecutionTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("MethodName") + .HasColumnName("MethodName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("Parameters") + .HasColumnName("Parameters") + .HasColumnType("nvarchar(2000)") + .HasMaxLength(2000); + + b.Property("ServiceName") + .HasColumnName("ServiceName") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); + + b.ToTable("AbpAuditLogActions"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AuditLogId") + .HasColumnName("AuditLogId") + .HasColumnType("uniqueidentifier"); + + b.Property("ChangeTime") + .HasColumnName("ChangeTime") + .HasColumnType("datetime2"); + + b.Property("ChangeType") + .HasColumnName("ChangeType") + .HasColumnType("tinyint"); + + b.Property("EntityId") + .IsRequired() + .HasColumnName("EntityId") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("EntityTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("EntityTypeFullName") + .IsRequired() + .HasColumnName("EntityTypeFullName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); + + b.ToTable("AbpEntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("EntityChangeId") + .HasColumnType("uniqueidentifier"); + + b.Property("NewValue") + .HasColumnName("NewValue") + .HasColumnType("nvarchar(512)") + .HasMaxLength(512); + + b.Property("OriginalValue") + .HasColumnName("OriginalValue") + .HasColumnType("nvarchar(512)") + .HasMaxLength(512); + + b.Property("PropertyName") + .IsRequired() + .HasColumnName("PropertyName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("PropertyTypeFullName") + .IsRequired() + .HasColumnName("PropertyTypeFullName") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("EntityChangeId"); + + b.ToTable("AbpEntityPropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("ProviderName") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpFeatureValues"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("Description") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsStatic") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("Regex") + .HasColumnType("nvarchar(512)") + .HasMaxLength(512); + + b.Property("RegexDescription") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ValueType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDefault") + .HasColumnName("IsDefault") + .HasColumnType("bit"); + + b.Property("IsPublic") + .HasColumnName("IsPublic") + .HasColumnType("bit"); + + b.Property("IsStatic") + .HasColumnName("IsStatic") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("NormalizedName") + .IsRequired() + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(1024)") + .HasMaxLength(1024); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnName("AccessFailedCount") + .HasColumnType("int") + .HasDefaultValue(0); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasColumnName("Email") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnName("EmailConfirmed") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnName("LockoutEnabled") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnName("Name") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("NormalizedEmail") + .IsRequired() + .HasColumnName("NormalizedEmail") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .IsRequired() + .HasColumnName("NormalizedUserName") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("PasswordHash") + .HasColumnName("PasswordHash") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("PhoneNumber") + .HasColumnName("PhoneNumber") + .HasColumnType("nvarchar(16)") + .HasMaxLength(16); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnName("PhoneNumberConfirmed") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("SecurityStamp") + .IsRequired() + .HasColumnName("SecurityStamp") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("Surname") + .HasColumnName("Surname") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnName("TwoFactorEnabled") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("UserName") + .IsRequired() + .HasColumnName("UserName") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(1024)") + .HasMaxLength(1024); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ProviderKey") + .IsRequired() + .HasColumnType("nvarchar(196)") + .HasMaxLength(196); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("Name") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasColumnName("Code") + .HasColumnType("nvarchar(95)") + .HasMaxLength(95); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnName("DisplayName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasColumnType("nvarchar(1000)") + .HasMaxLength(1000); + + b.Property("DisplayName") + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("IdentityServerApiResources"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => + { + b.Property("ApiResourceId") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.HasKey("ApiResourceId", "Type"); + + b.ToTable("IdentityServerApiClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b => + { + b.Property("ApiResourceId") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("Description") + .HasColumnType("nvarchar(1000)") + .HasMaxLength(1000); + + b.Property("DisplayName") + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("Emphasize") + .HasColumnType("bit"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ShowInDiscoveryDocument") + .HasColumnType("bit"); + + b.HasKey("ApiResourceId", "Name"); + + b.ToTable("IdentityServerApiScopes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b => + { + b.Property("ApiResourceId") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("Type") + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.HasKey("ApiResourceId", "Name", "Type"); + + b.ToTable("IdentityServerApiScopeClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b => + { + b.Property("ApiResourceId") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .HasColumnType("nvarchar(250)") + .HasMaxLength(250); + + b.Property("Value") + .HasColumnType("nvarchar(4000)") + .HasMaxLength(4000); + + b.Property("Description") + .HasColumnType("nvarchar(2000)") + .HasMaxLength(2000); + + b.Property("Expiration") + .HasColumnType("datetime2"); + + b.HasKey("ApiResourceId", "Type", "Value"); + + b.ToTable("IdentityServerApiSecrets"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AbsoluteRefreshTokenLifetime") + .HasColumnType("int"); + + b.Property("AccessTokenLifetime") + .HasColumnType("int"); + + b.Property("AccessTokenType") + .HasColumnType("int"); + + b.Property("AllowAccessTokensViaBrowser") + .HasColumnType("bit"); + + b.Property("AllowOfflineAccess") + .HasColumnType("bit"); + + b.Property("AllowPlainTextPkce") + .HasColumnType("bit"); + + b.Property("AllowRememberConsent") + .HasColumnType("bit"); + + b.Property("AlwaysIncludeUserClaimsInIdToken") + .HasColumnType("bit"); + + b.Property("AlwaysSendClientClaims") + .HasColumnType("bit"); + + b.Property("AuthorizationCodeLifetime") + .HasColumnType("int"); + + b.Property("BackChannelLogoutSessionRequired") + .HasColumnType("bit"); + + b.Property("BackChannelLogoutUri") + .HasColumnType("nvarchar(2000)") + .HasMaxLength(2000); + + b.Property("ClientClaimsPrefix") + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("ClientName") + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("ClientUri") + .HasColumnType("nvarchar(2000)") + .HasMaxLength(2000); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("ConsentLifetime") + .HasColumnType("int"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasColumnType("nvarchar(1000)") + .HasMaxLength(1000); + + b.Property("DeviceCodeLifetime") + .HasColumnType("int"); + + b.Property("EnableLocalLogin") + .HasColumnType("bit"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("FrontChannelLogoutSessionRequired") + .HasColumnType("bit"); + + b.Property("FrontChannelLogoutUri") + .HasColumnType("nvarchar(2000)") + .HasMaxLength(2000); + + b.Property("IdentityTokenLifetime") + .HasColumnType("int"); + + b.Property("IncludeJwtId") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("LogoUri") + .HasColumnType("nvarchar(2000)") + .HasMaxLength(2000); + + b.Property("PairWiseSubjectSalt") + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("ProtocolType") + .IsRequired() + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("RefreshTokenExpiration") + .HasColumnType("int"); + + b.Property("RefreshTokenUsage") + .HasColumnType("int"); + + b.Property("RequireClientSecret") + .HasColumnType("bit"); + + b.Property("RequireConsent") + .HasColumnType("bit"); + + b.Property("RequirePkce") + .HasColumnType("bit"); + + b.Property("SlidingRefreshTokenLifetime") + .HasColumnType("int"); + + b.Property("UpdateAccessTokenClaimsOnRefresh") + .HasColumnType("bit"); + + b.Property("UserCodeType") + .HasColumnType("nvarchar(100)") + .HasMaxLength(100); + + b.Property("UserSsoLifetime") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("IdentityServerClients"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .HasColumnType("nvarchar(250)") + .HasMaxLength(250); + + b.Property("Value") + .HasColumnType("nvarchar(250)") + .HasMaxLength(250); + + b.HasKey("ClientId", "Type", "Value"); + + b.ToTable("IdentityServerClientClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("Origin") + .HasColumnType("nvarchar(150)") + .HasMaxLength(150); + + b.HasKey("ClientId", "Origin"); + + b.ToTable("IdentityServerClientCorsOrigins"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("GrantType") + .HasColumnType("nvarchar(250)") + .HasMaxLength(250); + + b.HasKey("ClientId", "GrantType"); + + b.ToTable("IdentityServerClientGrantTypes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("Provider") + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.HasKey("ClientId", "Provider"); + + b.ToTable("IdentityServerClientIdPRestrictions"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("PostLogoutRedirectUri") + .HasColumnType("nvarchar(2000)") + .HasMaxLength(2000); + + b.HasKey("ClientId", "PostLogoutRedirectUri"); + + b.ToTable("IdentityServerClientPostLogoutRedirectUris"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("Key") + .HasColumnType("nvarchar(250)") + .HasMaxLength(250); + + b.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(2000)") + .HasMaxLength(2000); + + b.HasKey("ClientId", "Key"); + + b.ToTable("IdentityServerClientProperties"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("RedirectUri") + .HasColumnType("nvarchar(2000)") + .HasMaxLength(2000); + + b.HasKey("ClientId", "RedirectUri"); + + b.ToTable("IdentityServerClientRedirectUris"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("Scope") + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.HasKey("ClientId", "Scope"); + + b.ToTable("IdentityServerClientScopes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .HasColumnType("nvarchar(250)") + .HasMaxLength(250); + + b.Property("Value") + .HasColumnType("nvarchar(4000)") + .HasMaxLength(4000); + + b.Property("Description") + .HasColumnType("nvarchar(2000)") + .HasMaxLength(2000); + + b.Property("Expiration") + .HasColumnType("datetime2"); + + b.HasKey("ClientId", "Type", "Value"); + + b.ToTable("IdentityServerClientSecrets"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Devices.DeviceFlowCodes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("Data") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasMaxLength(50000); + + b.Property("DeviceCode") + .IsRequired() + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("Expiration") + .IsRequired() + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("SubjectId") + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("UserCode") + .IsRequired() + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.HasKey("Id"); + + b.HasIndex("DeviceCode") + .IsUnique(); + + b.HasIndex("Expiration"); + + b.HasIndex("UserCode") + .IsUnique(); + + b.ToTable("IdentityServerDeviceFlowCodes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Grants.PersistedGrant", b => + { + b.Property("Key") + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("Data") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasMaxLength(50000); + + b.Property("Expiration") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("SubjectId") + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("Type") + .IsRequired() + .HasColumnType("nvarchar(50)") + .HasMaxLength(50); + + b.HasKey("Key"); + + b.HasIndex("Expiration"); + + b.HasIndex("SubjectId", "ClientId", "Type"); + + b.ToTable("IdentityServerPersistedGrants"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityClaim", b => + { + b.Property("IdentityResourceId") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.HasKey("IdentityResourceId", "Type"); + + b.ToTable("IdentityServerIdentityClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityResource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasColumnType("nvarchar(1000)") + .HasMaxLength(1000); + + b.Property("DisplayName") + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("Emphasize") + .HasColumnType("bit"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(200)") + .HasMaxLength(200); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ShowInDiscoveryDocument") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.ToTable("IdentityServerIdentityResources"); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ProviderKey") + .IsRequired() + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("ProviderName") + .IsRequired() + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpPermissionGrants"); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("ProviderName") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(2048)") + .HasMaxLength(2048); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpSettings"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("AbpTenants"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(1024)") + .HasMaxLength(1024); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("Actions") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("EntityChanges") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.EntityChange", null) + .WithMany("PropertyChanges") + .HasForeignKey("EntityChangeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource", null) + .WithMany("UserClaims") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource", null) + .WithMany("Scopes") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiScope", null) + .WithMany("UserClaims") + .HasForeignKey("ApiResourceId", "Name") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource", null) + .WithMany("Secrets") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("Claims") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("AllowedCorsOrigins") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("AllowedGrantTypes") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("IdentityProviderRestrictions") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("PostLogoutRedirectUris") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("Properties") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("RedirectUris") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("AllowedScopes") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("ClientSecrets") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.IdentityResources.IdentityResource", null) + .WithMany("UserClaims") + .HasForeignKey("IdentityResourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.HasOne("Volo.Abp.TenantManagement.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20200525053551_Added_OrganizationUnits.cs b/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20200525053551_Added_OrganizationUnits.cs new file mode 100644 index 0000000000..faed450765 --- /dev/null +++ b/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20200525053551_Added_OrganizationUnits.cs @@ -0,0 +1,127 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace AuthServer.Host.Migrations +{ + public partial class Added_OrganizationUnits : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpOrganizationUnits", + columns: table => new + { + Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false, defaultValue: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), + TenantId = table.Column(nullable: true), + ParentId = table.Column(nullable: true), + Code = table.Column(maxLength: 95, nullable: false), + DisplayName = table.Column(maxLength: 128, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnits", x => x.Id); + table.ForeignKey( + name: "FK_AbpOrganizationUnits_AbpOrganizationUnits_ParentId", + column: x => x.ParentId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnitRoles", + columns: table => new + { + RoleId = table.Column(nullable: false), + OrganizationUnitId = table.Column(nullable: false), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnitRoles", x => new { x.OrganizationUnitId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserOrganizationUnits", + columns: table => new + { + UserId = table.Column(nullable: false), + OrganizationUnitId = table.Column(nullable: false), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserOrganizationUnits", x => new { x.OrganizationUnitId, x.UserId }); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", + table: "AbpOrganizationUnitRoles", + columns: new[] { "RoleId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_Code", + table: "AbpOrganizationUnits", + column: "Code"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_ParentId", + table: "AbpOrganizationUnits", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserOrganizationUnits_UserId_OrganizationUnitId", + table: "AbpUserOrganizationUnits", + columns: new[] { "UserId", "OrganizationUnitId" }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpOrganizationUnitRoles"); + + migrationBuilder.DropTable( + name: "AbpUserOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnits"); + } + } +} diff --git a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/AuthServerDbContextModelSnapshot.cs b/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/AuthServerDbContextModelSnapshot.cs index e7f114e76a..02d1201e31 100644 --- a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/AuthServerDbContextModelSnapshot.cs +++ b/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/AuthServerDbContextModelSnapshot.cs @@ -15,7 +15,7 @@ namespace AuthServer.Host.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.0") + .HasAnnotation("ProductVersion", "3.1.2") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -56,6 +56,8 @@ namespace AuthServer.Host.Migrations .HasMaxLength(256); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") .HasColumnType("nvarchar(max)"); b.Property("CorrelationId") @@ -164,6 +166,7 @@ namespace AuthServer.Host.Migrations .HasMaxLength(256); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -257,6 +260,7 @@ namespace AuthServer.Host.Migrations .HasMaxLength(64); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -385,6 +389,7 @@ namespace AuthServer.Host.Migrations .HasMaxLength(256); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -412,6 +417,7 @@ namespace AuthServer.Host.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -581,6 +587,7 @@ namespace AuthServer.Host.Migrations .HasMaxLength(1024); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("UserId") @@ -612,6 +619,7 @@ namespace AuthServer.Host.Migrations .HasMaxLength(196); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "LoginProvider"); @@ -621,6 +629,33 @@ namespace AuthServer.Host.Migrations b.ToTable("AbpUserLogins"); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.Property("UserId") @@ -630,6 +665,7 @@ namespace AuthServer.Host.Migrations .HasColumnType("uniqueidentifier"); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "RoleId"); @@ -653,6 +689,7 @@ namespace AuthServer.Host.Migrations .HasMaxLength(128); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.Property("Value") @@ -663,6 +700,106 @@ namespace AuthServer.Host.Migrations b.ToTable("AbpUserTokens"); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasColumnName("Code") + .HasColumnType("nvarchar(95)") + .HasMaxLength(95); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnName("DisplayName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles"); + }); + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b => { b.Property("Id") @@ -1218,6 +1355,8 @@ namespace AuthServer.Host.Migrations .HasMaxLength(200); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") .HasColumnType("nvarchar(max)"); b.Property("CreationTime") @@ -1370,6 +1509,7 @@ namespace AuthServer.Host.Migrations .HasMaxLength(64); b.Property("TenantId") + .HasColumnName("TenantId") .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -1540,6 +1680,21 @@ namespace AuthServer.Host.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { b.HasOne("Volo.Abp.Identity.IdentityRole", null) @@ -1564,6 +1719,28 @@ namespace AuthServer.Host.Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => { b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource", null) From da30990140961eea166c4098cd6e48ae243bef4d Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 25 May 2020 22:37:01 +0800 Subject: [PATCH 08/20] Add virtual file explorer module documentation. --- docs/en/Modules/Index.md | 1 + docs/en/Modules/Virtual-File-Explorer.md | 80 ++++++++++++++++++ docs/en/images/virtual-file-explorer.png | Bin 0 -> 47748 bytes docs/zh-Hans/Modules/Index.md | 1 + docs/zh-Hans/Modules/Virtual-File-Explorer.md | 80 ++++++++++++++++++ docs/zh-Hans/images/virtual-file-explorer.png | Bin 0 -> 47748 bytes 6 files changed, 162 insertions(+) create mode 100644 docs/en/Modules/Virtual-File-Explorer.md create mode 100644 docs/en/images/virtual-file-explorer.png create mode 100644 docs/zh-Hans/Modules/Virtual-File-Explorer.md create mode 100644 docs/zh-Hans/images/virtual-file-explorer.png diff --git a/docs/en/Modules/Index.md b/docs/en/Modules/Index.md index 2ffb509667..71bf58333c 100644 --- a/docs/en/Modules/Index.md +++ b/docs/en/Modules/Index.md @@ -23,6 +23,7 @@ There are some **free and open source** application modules developed and mainta * **[Setting Management](Setting-Management.md)**: Used to persist and manage the [settings](../Settings.md). * **Tenant Management**: Manages tenants for a [multi-tenant](../Multi-Tenancy.md) application. * **Users**: Abstract users, so other modules can depend on this module instead of the Identity module. +* [**Virtual File Explorer**](Virtual-File-Explorer.md): Provided a simple UI to view files in [virtual file system](../Virtual-File-System.md). See [the GitHub repository](https://github.com/abpframework/abp/tree/master/modules) for source code of all modules. diff --git a/docs/en/Modules/Virtual-File-Explorer.md b/docs/en/Modules/Virtual-File-Explorer.md new file mode 100644 index 0000000000..81059ff870 --- /dev/null +++ b/docs/en/Modules/Virtual-File-Explorer.md @@ -0,0 +1,80 @@ +# Virtual File Explorer Module + +## What is Virtual File Explorer Module? + +Virtual File Explorer Module provided a simple UI to view all files in [virtual file system](../Virtual-File-System.md). + +> Virtual File Explorer Module is not installed for [the startup templates](../Startup-Templates/Index.md). So, you need to manually add this module to your application. + +### Installation + +#### 1- Referencing Virtual File Explorer Module Packages + +It is recommended to use the ABP CLI to install the module, open the CMD window in the solution file (`.sln`) directory, and run the following command: + +`abp add-module Volo.VirtualFileExplorer` + +Or you can also manually install nuget package to `Acme.MyProject.Web` project: + +* Install [Volo.Abp.VirtualFileExplorer.Web](https://www.nuget.org/packages/Volo.Abp.VirtualFileExplorer.Web/) nuget package to `Acme.MyProject.Web` project. + + `Install-Package Volo.Abp.VirtualFileExplorer.Web` + +#### 2- Adding Module Dependencies + + * Open `MyProjectWebModule.cs`and add `typeof(AbpVirtualFileExplorerWebModule)` as shown below; + + ```csharp + [DependsOn( + typeof(AbpVirtualFileExplorerWebModule), + typeof(MyProjectApplicationModule), + typeof(MyProjectEntityFrameworkCoreModule), + typeof(AbpAutofacModule), + typeof(AbpIdentityWebModule), + typeof(AbpAccountWebModule), + typeof(AbpAspNetCoreMvcUiBasicThemeModule) + )] + public class MyProjectWebModule : AbpModule + { + //... + } + ``` + +#### 3- Adding NPM Package + + * Open `package.json` and add `@abp/virtual-file-explorer": "^2.9.0` as shown below: + + ```json + { + "version": "1.0.0", + "name": "my-app", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.basic": "^2.9.0", + "@abp/virtual-file-explorer": "^2.9.0" + } + } + ``` + + Then open the command line terminal in the `Acme.MyProject.Web` project folder and run the following command: + + 1. `yarn` + 2. `gulp` + +That's all,Now run the application and Navigate to `/VirtualFileExplorer`. You will see virtual file explorer page: + +![Virtual-File-Explorer](../images/virtual-file-explorer.png) + +### Options + +You can disabled virtual file explorer module via `AbpVirtualFileExplorerOptions` options: + +```csharp +public override void PreConfigureServices(ServiceConfigurationContext context) +{ + PreConfigure(options => + { + options.IsEnabled = false; + }); +} +``` \ No newline at end of file diff --git a/docs/en/images/virtual-file-explorer.png b/docs/en/images/virtual-file-explorer.png new file mode 100644 index 0000000000000000000000000000000000000000..e49d0f21117db8e14fe1575a74929ba99432141c GIT binary patch literal 47748 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 [启动模板](../Startup-Templates/Index.md)默认并没有安装这个模块,所以你需要手动安装到应用程序. + +### 安装 + +#### 1- 引用虚拟文件浏览器模块包 + +建议使用ABP CLI安装模块,在解决方案文件 (`.sln`) 目录打开 `CMD` 窗口,运行以下命令: + +`abp add-module Volo.VirtualFileExplorer` + +或者你也可以手动安装nuget包到 `Acme.MyProject.Web` 项目: + +* 安装[Volo.Abp.VirtualFileExplorer.Web](https://www.nuget.org/packages/Volo.Abp.VirtualFileExplorer.Web/) nuget包到 `Acme.MyProject.Web` 项目. + + `Install-Package Volo.Abp.VirtualFileExplorer.Web` + +#### 2- 添加模块依赖 + +* 打开 `MyProjectWebModule.cs` 并且添加 `typeof(AbpVirtualFileExplorerWebModule)` 如下所示; + + ```csharp + [DependsOn( + typeof(AbpVirtualFileExplorerWebModule), + typeof(MyProjectApplicationModule), + typeof(MyProjectEntityFrameworkCoreModule), + typeof(AbpAutofacModule), + typeof(AbpIdentityWebModule), + typeof(AbpAccountWebModule), + typeof(AbpAspNetCoreMvcUiBasicThemeModule) + )] + public class MyProjectWebModule : AbpModule + { + //... + } + ``` + +#### 3- 添加NPM包 + + * 打开 `package.json` 添加 `@abp/virtual-file-explorer": "^2.9.0` 如下所示: + + ```json + { + "version": "1.0.0", + "name": "my-app", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.basic": "^2.9.0", + "@abp/virtual-file-explorer": "^2.9.0" + } + } + ``` + + 然后在 `Acme.MyProject.Web` 项目目录打开命令行终端运行以下命令: + + 1. `yarn` + 2. `gulp` + +这就是全部,运行应用程序导航到 `/VirtualFileExplorer`. 你会看到虚拟文件浏览器页面: + +![Virtual-File-Explorer](../images/virtual-file-explorer.png) + +### 选项 + +你可以通过 `AbpVirtualFileExplorerOptions` 选项禁用虚拟文件浏览器模块: + +```csharp +public override void PreConfigureServices(ServiceConfigurationContext context) +{ + PreConfigure(options => + { + options.IsEnabled = false; + }); +} +``` \ No newline at end of file diff --git a/docs/zh-Hans/images/virtual-file-explorer.png b/docs/zh-Hans/images/virtual-file-explorer.png new file mode 100644 index 0000000000000000000000000000000000000000..e49d0f21117db8e14fe1575a74929ba99432141c GIT binary patch literal 47748 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 Date: Tue, 26 May 2020 15:28:08 +0800 Subject: [PATCH 09/20] Change the ErrorMessage of StringLengthAttribute according to the situation. Resolve #4094 --- .../Validation/ValidationAttributeHelper.cs | 24 ++++++++++++++----- .../Validation/ValidationTestController.cs | 4 ++-- .../ValidationTestController_Tests.cs | 2 +- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/ValidationAttributeHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/ValidationAttributeHelper.cs index 955b83c48f..8d5a7abfb1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/ValidationAttributeHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/ValidationAttributeHelper.cs @@ -1,8 +1,5 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.Reflection; -using System.Text; namespace Volo.Abp.AspNetCore.Mvc.Validation { @@ -11,10 +8,25 @@ namespace Volo.Abp.AspNetCore.Mvc.Validation private static readonly PropertyInfo ValidationAttributeErrorMessageStringProperty = typeof(ValidationAttribute) .GetProperty("ErrorMessageString", BindingFlags.Instance | BindingFlags.NonPublic); + private static readonly PropertyInfo ValidationAttributeCustomErrorMessageSetProperty = typeof(ValidationAttribute) + .GetProperty("CustomErrorMessageSet", BindingFlags.Instance | BindingFlags.NonPublic); + public static void SetDefaultErrorMessage(ValidationAttribute validationAttribute) { - validationAttribute.ErrorMessage = - ValidationAttributeErrorMessageStringProperty.GetValue(validationAttribute) as string; + if (validationAttribute is StringLengthAttribute stringLength && stringLength.MinimumLength != 0) + { + var customErrorMessageSet = ValidationAttributeCustomErrorMessageSetProperty.GetValue(validationAttribute) as bool?; + if (customErrorMessageSet != true) + { + validationAttribute.ErrorMessage = + "The field {0} must be a string with a minimum length of {2} and a maximum length of {1}."; + } + } + else + { + validationAttribute.ErrorMessage = + ValidationAttributeErrorMessageStringProperty.GetValue(validationAttribute) as string; + } } } } diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Validation/ValidationTestController.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Validation/ValidationTestController.cs index 6bb9a5ae94..57cb40219b 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Validation/ValidationTestController.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Validation/ValidationTestController.cs @@ -35,7 +35,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Validation public class ValidationTest1Model { [Required] - [MinLength(2)] + [StringLength(5, MinimumLength = 2)] public string Value1 { get; set; } } @@ -53,4 +53,4 @@ namespace Volo.Abp.AspNetCore.Mvc.Validation } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Validation/ValidationTestController_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Validation/ValidationTestController_Tests.cs index 361db7845a..99e027f85a 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Validation/ValidationTestController_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Validation/ValidationTestController_Tests.cs @@ -30,7 +30,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Validation { var result = await GetResponseAsObjectAsync("/api/validation-test/object-result-action?value1=a", HttpStatusCode.BadRequest); //value1 has min length of 2 chars. result.Error.ValidationErrors.Length.ShouldBeGreaterThan(0); - result.Error.ValidationErrors[0].Message.ShouldBe("Değer Bir alanı en az '2' uzunluğunda bir metin ya da dizi olmalıdır."); + result.Error.ValidationErrors[0].Message.ShouldBe("Değer Bir alanı en az 2, en fazla 5 uzunluğunda bir metin olmalıdır."); } } From 427d9a560435307c62534ec33611324c45e2a574 Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Tue, 26 May 2020 15:33:18 +0800 Subject: [PATCH 10/20] Handle the case where customErrorMessageSet is true. --- .../Mvc/Validation/ValidationAttributeHelper.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/ValidationAttributeHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/ValidationAttributeHelper.cs index 8d5a7abfb1..14ff42e320 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/ValidationAttributeHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/ValidationAttributeHelper.cs @@ -20,13 +20,12 @@ namespace Volo.Abp.AspNetCore.Mvc.Validation { validationAttribute.ErrorMessage = "The field {0} must be a string with a minimum length of {2} and a maximum length of {1}."; + return; } } - else - { - validationAttribute.ErrorMessage = - ValidationAttributeErrorMessageStringProperty.GetValue(validationAttribute) as string; - } + + validationAttribute.ErrorMessage = + ValidationAttributeErrorMessageStringProperty.GetValue(validationAttribute) as string; } } } From e853427d19bbf70737d9d25f4bd1ad0ac61ff14b Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Wed, 27 May 2020 02:14:39 +0300 Subject: [PATCH 11/20] refactor(theme-basic): remove unneccessary variable --- .../application-layout.component.html | 15 ++++++++++++--- .../application-layout.component.ts | 6 +----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html b/npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html index 1faaafaa58..2da4769955 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html @@ -22,14 +22,23 @@ diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.ts index e996d2f786..9c90292d96 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.ts @@ -15,8 +15,6 @@ export class ApplicationLayoutComponent implements AfterViewInit, OnDestroy { // required for dynamic component static type = eLayoutType.application; - isDropdownChildDynamic: boolean; - isCollapsed = true; smallScreen: boolean; // do not set true or false @@ -31,8 +29,7 @@ export class ApplicationLayoutComponent implements AfterViewInit, OnDestroy { private checkWindowWidth() { setTimeout(() => { - if (window.innerWidth < 768) { - this.isDropdownChildDynamic = false; + if (window.innerWidth < 992) { if (this.smallScreen === false) { this.isCollapsed = false; setTimeout(() => { @@ -41,7 +38,6 @@ export class ApplicationLayoutComponent implements AfterViewInit, OnDestroy { } this.smallScreen = true; } else { - this.isDropdownChildDynamic = true; this.smallScreen = false; } }, 0); From 52156ac604cb29f2da87214b5c5b7136b6841a55 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Wed, 27 May 2020 02:16:08 +0300 Subject: [PATCH 12/20] fix(theme-basic): change smallScreen breakpoint px resolves #3757 --- .../components/routes/routes.component.html | 4 +--- .../lib/components/routes/routes.component.ts | 20 +++---------------- .../theme-basic/src/lib/constants/styles.ts | 2 +- 3 files changed, 5 insertions(+), 21 deletions(-) diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html b/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html index 226e19c39e..6437233cb1 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html @@ -77,16 +77,14 @@ class="dropdown-submenu" ngbDropdown #dropdownSubmenu="ngbDropdown" - [display]="isDropdownChildDynamic ? 'dynamic' : 'static'" placement="right-top" [autoClose]="true" *abpPermission="child.requiredPolicy" - (openChange)="openChange($event, childrenContainer)" >
diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts index 22b30426fa..2ed204e0b0 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts @@ -1,8 +1,8 @@ -import { Component, OnInit, TrackByFunction, Input, Renderer2 } from '@angular/core'; -import { Observable } from 'rxjs'; import { ABP, ConfigState } from '@abp/ng.core'; -import { map } from 'rxjs/operators'; +import { Component, Input, Renderer2, TrackByFunction } from '@angular/core'; import { Select } from '@ngxs/store'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; @Component({ selector: 'abp-routes', @@ -15,9 +15,6 @@ export class RoutesComponent { @Input() smallScreen: boolean; - @Input() - isDropdownChildDynamic: boolean; - get visibleRoutes$(): Observable { return this.routes$.pipe(map(routes => getVisibleRoutes(routes))); } @@ -25,17 +22,6 @@ export class RoutesComponent { trackByFn: TrackByFunction = (_, item) => item.name; constructor(private renderer: Renderer2) {} - - openChange(event: boolean, childrenContainer: HTMLDivElement) { - if (!event) { - Object.keys(childrenContainer.style) - .filter(key => Number.isInteger(+key)) - .forEach(key => { - this.renderer.removeStyle(childrenContainer, childrenContainer.style[key]); - }); - this.renderer.removeStyle(childrenContainer, 'left'); - } - } } function getVisibleRoutes(routes: ABP.FullRoute[]) { diff --git a/npm/ng-packs/packages/theme-basic/src/lib/constants/styles.ts b/npm/ng-packs/packages/theme-basic/src/lib/constants/styles.ts index 975a3c02a1..0d9ebcc300 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/constants/styles.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/constants/styles.ts @@ -46,7 +46,7 @@ export default ` .container > .card { box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; } -@media screen and (min-width: 768px) { +@media screen and (min-width: 992px) { .navbar .dropdown:hover > .dropdown-menu { display: block; } From 52784b4429253b2a6d7dbc09c37b2c1e768afd59 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Wed, 27 May 2020 16:53:25 +0300 Subject: [PATCH 13/20] feat: add general invalid blueprint to basic theme --- npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts b/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts index 5e50e6f33c..1a2b22c22b 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts @@ -36,6 +36,7 @@ export const LAYOUTS = [ApplicationLayoutComponent, AccountLayoutComponent, Empt blueprints: { creditCard: 'AbpValidation::ThisFieldIsNotAValidCreditCardNumber.', email: 'AbpValidation::ThisFieldIsNotAValidEmailAddress.', + invalid: 'AbpValidation::ThisFieldIsNotValid.', max: 'AbpValidation::ThisFieldMustBeBetween{0}And{1}[{{ min }},{{ max }}]', maxlength: 'AbpValidation::ThisFieldMustBeAStringOrArrayTypeWithAMaximumLengthOf{0}[{{ requiredLength }}]', From 4a21750f1c0d9f72f2e5f1eaa9c105abc3c12fac Mon Sep 17 00:00:00 2001 From: Arkat Erol Date: Wed, 27 May 2020 17:33:37 +0300 Subject: [PATCH 14/20] missing double quotes fixed --- nupkg/common.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nupkg/common.ps1 b/nupkg/common.ps1 index d056ae032d..3b5ae4b1df 100644 --- a/nupkg/common.ps1 +++ b/nupkg/common.ps1 @@ -234,5 +234,5 @@ $projects = ( "modules/users/src/Volo.Abp.Users.MongoDB", # modules/virtual-file-explorer - "modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web + "modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web" ) \ No newline at end of file From 98b6bf026da7de28a62d0e13767526daef3f4f36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 27 May 2020 19:17:52 +0300 Subject: [PATCH 15/20] Remove unused (name)spaces. --- .../FileSystem/FileSystemBlobProviderConfiguration.cs | 1 - .../Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/IBlobProvider.cs | 3 +-- .../FileSystem/AbpBlobStoringFileSystemTestModule.cs | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProviderConfiguration.cs b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProviderConfiguration.cs index 4d4a786d16..3d3a5d5968 100644 --- a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProviderConfiguration.cs +++ b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProviderConfiguration.cs @@ -2,7 +2,6 @@ { public class FileSystemBlobProviderConfiguration { - public string BasePath { get => _containerConfiguration.GetConfiguration(FileSystemBlobProviderConfigurationNames.BasePath); diff --git a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/IBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/IBlobProvider.cs index d7332589c5..bb9b42d37d 100644 --- a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/IBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/IBlobProvider.cs @@ -1,5 +1,4 @@ -using System; -using System.IO; +using System.IO; using System.Threading.Tasks; namespace Volo.Abp.BlobStoring diff --git a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/AbpBlobStoringFileSystemTestModule.cs b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/AbpBlobStoringFileSystemTestModule.cs index 35fc30b84d..f151d8786d 100644 --- a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/AbpBlobStoringFileSystemTestModule.cs +++ b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/AbpBlobStoringFileSystemTestModule.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using Volo.Abp.BlobStoring.FileSystem.TestObjects; using Volo.Abp.Modularity; namespace Volo.Abp.BlobStoring.FileSystem From 49da37d1ad442192cb1ad1e16ef1917c53df73a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Thu, 28 May 2020 05:32:24 +0300 Subject: [PATCH 16/20] Added initial tests for the file system blob container. --- .../FileSystem/FileSystemBlobProvider.cs | 1 + .../Volo/Abp/BlobStoring/BlobContainer.cs | 4 +- .../BlobContainerConfigurations.cs | 34 ++++++++++---- ...lo.Abp.BlobStoring.FileSystem.Tests.csproj | 1 + .../AbpBlobStoringFileSystemTestModule.cs | 7 +-- .../BlogFilePathCalculator_Tests.cs | 2 +- .../FileSystemBlobContainer_Tests.cs | 10 +++++ .../FileSystem/TestObjects/TestContainer.cs | 8 ---- .../Abp/BlobStoring/BlobContainer_Tests.cs | 45 +++++++++++++++++++ 9 files changed, 90 insertions(+), 22 deletions(-) create mode 100644 framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobContainer_Tests.cs delete mode 100644 framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/TestObjects/TestContainer.cs create mode 100644 framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs diff --git a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs index b927bdbf47..a06c2c1018 100644 --- a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs @@ -6,6 +6,7 @@ using Volo.Abp.IO; namespace Volo.Abp.BlobStoring.FileSystem { //TODO: What if the file is being used on create, delete or read? + //TODO: Implement all methods truly async! public class FileSystemBlobProvider : BlobProviderBase, ITransientDependency { diff --git a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainer.cs b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainer.cs index 700549e957..789271b6ee 100644 --- a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainer.cs +++ b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainer.cs @@ -147,11 +147,11 @@ namespace Volo.Abp.BlobStoring ); } - public virtual Task GetAsync( + public virtual async Task GetAsync( string name, CancellationToken cancellationToken = default) { - var stream = Provider.GetOrNullAsync( + var stream = await Provider.GetOrNullAsync( new BlobProviderGetArgs( ContainerName, Configuration, diff --git a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerConfigurations.cs b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerConfigurations.cs index 5e17793f21..ed2c5afe04 100644 --- a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerConfigurations.cs +++ b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerConfigurations.cs @@ -6,14 +6,17 @@ namespace Volo.Abp.BlobStoring { public class BlobContainerConfigurations { - public BlobContainerConfiguration Default { get; } + private BlobContainerConfiguration Default => GetConfiguration(); private readonly Dictionary _containers; public BlobContainerConfigurations() { - Default = new BlobContainerConfiguration(); - _containers = new Dictionary(); + _containers = new Dictionary + { + //Add default container + [BlobContainerNameAttribute.GetContainerName()] = new BlobContainerConfiguration() + }; } public BlobContainerConfigurations Configure( @@ -31,9 +34,14 @@ namespace Volo.Abp.BlobStoring { Check.NotNullOrWhiteSpace(name, nameof(name)); Check.NotNull(configureAction, nameof(configureAction)); - - configureAction(_containers.GetOrAdd(name, () => new BlobContainerConfiguration(Default))); - + + configureAction( + _containers.GetOrAdd( + name, + () => new BlobContainerConfiguration(Default) + ) + ); + return this; } @@ -42,7 +50,17 @@ namespace Volo.Abp.BlobStoring configureAction(Default); return this; } - + + public BlobContainerConfigurations ConfigureAll(Action configureAction) + { + foreach (var container in _containers) + { + configureAction(container.Key, container.Value); + } + + return this; + } + [NotNull] public BlobContainerConfiguration GetConfiguration() { @@ -54,7 +72,7 @@ namespace Volo.Abp.BlobStoring { Check.NotNullOrWhiteSpace(name, nameof(name)); - return _containers.GetOrDefault(name) ?? + return _containers.GetOrDefault(name) ?? Default; } } diff --git a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo.Abp.BlobStoring.FileSystem.Tests.csproj b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo.Abp.BlobStoring.FileSystem.Tests.csproj index 1ac7ba2414..b2741af89a 100644 --- a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo.Abp.BlobStoring.FileSystem.Tests.csproj +++ b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo.Abp.BlobStoring.FileSystem.Tests.csproj @@ -12,6 +12,7 @@ + diff --git a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/AbpBlobStoringFileSystemTestModule.cs b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/AbpBlobStoringFileSystemTestModule.cs index f151d8786d..a2ab6052bd 100644 --- a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/AbpBlobStoringFileSystemTestModule.cs +++ b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/AbpBlobStoringFileSystemTestModule.cs @@ -5,7 +5,8 @@ using Volo.Abp.Modularity; namespace Volo.Abp.BlobStoring.FileSystem { [DependsOn( - typeof(AbpBlobStoringFileSystemModule) + typeof(AbpBlobStoringFileSystemModule), + typeof(AbpBlobStoringTestModule) )] public class AbpBlobStoringFileSystemTestModule : AbpModule { @@ -13,9 +14,9 @@ namespace Volo.Abp.BlobStoring.FileSystem { Configure(options => { - options.Containers.ConfigureDefault(container => + options.Containers.ConfigureAll((containerName, containerConfiguration) => { - container.UseFileSystem(fileSystem => + containerConfiguration.UseFileSystem(fileSystem => { fileSystem.BasePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); }); diff --git a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/BlogFilePathCalculator_Tests.cs b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/BlogFilePathCalculator_Tests.cs index 2493dab733..f7b55de401 100644 --- a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/BlogFilePathCalculator_Tests.cs +++ b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/BlogFilePathCalculator_Tests.cs @@ -45,7 +45,7 @@ namespace Volo.Abp.BlobStoring.FileSystem ).ShouldBe($"C:{separator}my-files{separator}host{separator}my-blob"); } - private BlobProviderArgs GetArgs( + private static BlobProviderArgs GetArgs( string basePath, string containerName, string blobName, diff --git a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobContainer_Tests.cs b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobContainer_Tests.cs new file mode 100644 index 0000000000..cf2ca82398 --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobContainer_Tests.cs @@ -0,0 +1,10 @@ +namespace Volo.Abp.BlobStoring.FileSystem +{ + public class FileSystemBlobContainer_Tests : BlobContainer_Tests + { + public FileSystemBlobContainer_Tests() + { + + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/TestObjects/TestContainer.cs b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/TestObjects/TestContainer.cs deleted file mode 100644 index 91ac79f6c3..0000000000 --- a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/TestObjects/TestContainer.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Volo.Abp.BlobStoring.FileSystem.TestObjects -{ - [BlobContainerName("TestContainer")] - public class TestContainer - { - - } -} \ No newline at end of file diff --git a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs new file mode 100644 index 0000000000..195e51f335 --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs @@ -0,0 +1,45 @@ +using System; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.BlobStoring.TestObjects; +using Volo.Abp.Modularity; +using Volo.Abp.Testing; +using Xunit; + +namespace Volo.Abp.BlobStoring +{ + public abstract class BlobContainer_Tests : AbpIntegratedTest + where TStartupModule : IAbpModule + { + protected IBlobContainer Container { get; } + + protected BlobContainer_Tests() + { + Container = GetRequiredService>(); + } + + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + [Fact] + public async Task SaveAsync() + { + var testContent = "test content".GetBytes(); + + using (var memoryStream = new MemoryStream(testContent)) + { + await Container.SaveAsync("test-blob-1", memoryStream); + } + + using (var stream = await Container.GetAsync("test-blob-1")) + { + var result = await stream.GetAllBytesAsync(); + result.SequenceEqual(testContent).ShouldBeTrue(); + } + } + } +} \ No newline at end of file From ed82af47ddcdd65be1927e718274b23030a82909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Thu, 28 May 2020 06:05:31 +0300 Subject: [PATCH 17/20] Completed integration tests for the file blob store --- .../FileSystem/FileSystemBlobProvider.cs | 1 - .../BlobStoring/BlobContainerExtensions.cs | 57 +++++++++++++++++++ .../System/IO/AbpStreamExtensions.cs | 16 +++++- .../Volo.Abp.Core/Volo/Abp/AbpException.cs | 15 ----- .../Volo/Abp/AbpInitializationException.cs | 15 ----- .../Volo/Abp/AbpShutdownException.cs | 31 ++++++++++ .../Volo/Abp/IO/DirectoryHelper.cs | 28 ++++++--- .../Volo/Abp/Modularity/ModuleManager.cs | 4 +- .../AbpBlobStoringFileSystemTestModule.cs | 18 +++++- .../Abp/BlobStoring/BlobContainer_Tests.cs | 57 ++++++++++++++----- 10 files changed, 185 insertions(+), 57 deletions(-) create mode 100644 framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerExtensions.cs create mode 100644 framework/src/Volo.Abp.Core/Volo/Abp/AbpShutdownException.cs diff --git a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs index a06c2c1018..9194a78652 100644 --- a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs @@ -33,7 +33,6 @@ namespace Volo.Abp.BlobStoring.FileSystem await args.BlobStream.CopyToAsync( fileStream, - 81920, //this is already the default value, but needed to set to be able to pass the cancellationToken args.CancellationToken ); diff --git a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerExtensions.cs b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerExtensions.cs new file mode 100644 index 0000000000..58ae4ac593 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerExtensions.cs @@ -0,0 +1,57 @@ +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Volo.Abp.BlobStoring +{ + public static class BlobContainerExtensions + { + public static async Task SaveAsync( + this IBlobContainer container, + string name, + byte[] bytes, + bool overrideExisting = false, + CancellationToken cancellationToken = default + ) + { + using (var memoryStream = new MemoryStream(bytes)) + { + await container.SaveAsync( + name, + memoryStream, + overrideExisting, + cancellationToken + ); + } + } + + public static async Task GetAllBytesAsync( + this IBlobContainer container, + string name, + CancellationToken cancellationToken = default) + { + using (var stream = await container.GetAsync(name, cancellationToken)) + { + return await stream.GetAllBytesAsync(cancellationToken); + } + } + + public static async Task GetAllBytesOrNullAsync( + this IBlobContainer container, + string name, + CancellationToken cancellationToken = default) + { + var stream = await container.GetOrNullAsync(name, cancellationToken); + if (stream == null) + { + return null; + } + + using (stream) + { + return await stream.GetAllBytesAsync(cancellationToken); + } + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs b/framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs index e87ab67527..466d73b2a7 100644 --- a/framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs +++ b/framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; namespace System.IO { @@ -13,13 +14,22 @@ namespace System.IO } } - public static async Task GetAllBytesAsync(this Stream stream) + public static async Task GetAllBytesAsync(this Stream stream, CancellationToken cancellationToken = default) { using (var memoryStream = new MemoryStream()) { - await stream.CopyToAsync(memoryStream); + await stream.CopyToAsync(memoryStream, cancellationToken); return memoryStream.ToArray(); } } + + public static Task CopyToAsync(this Stream stream, Stream destination, CancellationToken cancellationToken) + { + return stream.CopyToAsync( + destination, + 81920, //this is already the default value, but needed to set to be able to pass the cancellationToken + cancellationToken + ); + } } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs b/framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs index 39792ecf34..ccc4a57dbe 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs @@ -8,38 +8,23 @@ namespace Volo.Abp /// public class AbpException : Exception { - /// - /// Creates a new object. - /// public AbpException() { } - /// - /// Creates a new object. - /// - /// Exception message public AbpException(string message) : base(message) { } - /// - /// Creates a new object. - /// - /// Exception message - /// Inner exception public AbpException(string message, Exception innerException) : base(message, innerException) { } - /// - /// Constructor for serializing. - /// public AbpException(SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context) { diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/AbpInitializationException.cs b/framework/src/Volo.Abp.Core/Volo/Abp/AbpInitializationException.cs index 1bcd513168..31d93d69bd 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/AbpInitializationException.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/AbpInitializationException.cs @@ -5,38 +5,23 @@ namespace Volo.Abp { public class AbpInitializationException : AbpException { - /// - /// Creates a new object. - /// public AbpInitializationException() { } - /// - /// Creates a new object. - /// - /// Exception message public AbpInitializationException(string message) : base(message) { } - /// - /// Creates a new object. - /// - /// Exception message - /// Inner exception public AbpInitializationException(string message, Exception innerException) : base(message, innerException) { } - /// - /// Constructor for serializing. - /// public AbpInitializationException(SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context) { diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/AbpShutdownException.cs b/framework/src/Volo.Abp.Core/Volo/Abp/AbpShutdownException.cs new file mode 100644 index 0000000000..1261c4f8b3 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/AbpShutdownException.cs @@ -0,0 +1,31 @@ +using System; +using System.Runtime.Serialization; + +namespace Volo.Abp +{ + public class AbpShutdownException : AbpException + { + public AbpShutdownException() + { + + } + + public AbpShutdownException(string message) + : base(message) + { + + } + + public AbpShutdownException(string message, Exception innerException) + : base(message, innerException) + { + + } + + public AbpShutdownException(SerializationInfo serializationInfo, StreamingContext context) + : base(serializationInfo, context) + { + + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/IO/DirectoryHelper.cs b/framework/src/Volo.Abp.Core/Volo/Abp/IO/DirectoryHelper.cs index 23f8de610a..661ba76b52 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/IO/DirectoryHelper.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/IO/DirectoryHelper.cs @@ -16,7 +16,23 @@ namespace Volo.Abp.IO Directory.CreateDirectory(directory); } } - + + public static void DeleteIfExists(string directory) + { + if (Directory.Exists(directory)) + { + Directory.Delete(directory); + } + } + + public static void DeleteIfExists(string directory, bool recursive) + { + if (Directory.Exists(directory)) + { + Directory.Delete(directory, recursive); + } + } + public static void CreateIfNotExists(DirectoryInfo directory) { if (!directory.Exists) @@ -36,7 +52,8 @@ namespace Volo.Abp.IO ); } - public static bool IsSubDirectoryOf([NotNull] DirectoryInfo parentDirectory, [NotNull] DirectoryInfo childDirectory) + public static bool IsSubDirectoryOf([NotNull] DirectoryInfo parentDirectory, + [NotNull] DirectoryInfo childDirectory) { Check.NotNull(parentDirectory, nameof(parentDirectory)); Check.NotNull(childDirectory, nameof(childDirectory)); @@ -66,10 +83,7 @@ namespace Volo.Abp.IO Directory.SetCurrentDirectory(targetDirectory); - return new DisposeAction(() => - { - Directory.SetCurrentDirectory(currentDirectory); - }); + return new DisposeAction(() => { Directory.SetCurrentDirectory(currentDirectory); }); } } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleManager.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleManager.cs index e594a24603..70b9036150 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleManager.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleManager.cs @@ -44,7 +44,7 @@ namespace Volo.Abp.Modularity } catch (Exception ex) { - throw new AbpInitializationException($"An error occurred during the initialize {contributor.GetType().FullName} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex); + throw new AbpInitializationException($"An error occurred during the initialize {contributor.GetType().FullName} phase of the module {module.Type.AssemblyQualifiedName}: {ex.Message}. See the inner exception for details.", ex); } } } @@ -76,7 +76,7 @@ namespace Volo.Abp.Modularity } catch (Exception ex) { - throw new AbpInitializationException($"An error occurred during the shutdown {contributor.GetType().FullName} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex); + throw new AbpShutdownException($"An error occurred during the shutdown {contributor.GetType().FullName} phase of the module {module.Type.AssemblyQualifiedName}: {ex.Message}. See the inner exception for details.", ex); } } } diff --git a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/AbpBlobStoringFileSystemTestModule.cs b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/AbpBlobStoringFileSystemTestModule.cs index a2ab6052bd..a18f8e40af 100644 --- a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/AbpBlobStoringFileSystemTestModule.cs +++ b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/AbpBlobStoringFileSystemTestModule.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using Volo.Abp.IO; using Volo.Abp.Modularity; namespace Volo.Abp.BlobStoring.FileSystem @@ -10,6 +11,16 @@ namespace Volo.Abp.BlobStoring.FileSystem )] public class AbpBlobStoringFileSystemTestModule : AbpModule { + private readonly string _testDirectoryPath; + + public AbpBlobStoringFileSystemTestModule() + { + _testDirectoryPath = Path.Combine( + Path.GetTempPath(), + Guid.NewGuid().ToString("N") + ); + } + public override void ConfigureServices(ServiceConfigurationContext context) { Configure(options => @@ -18,10 +29,15 @@ namespace Volo.Abp.BlobStoring.FileSystem { containerConfiguration.UseFileSystem(fileSystem => { - fileSystem.BasePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + fileSystem.BasePath = _testDirectoryPath; }); }); }); } + + public override void OnApplicationShutdown(ApplicationShutdownContext context) + { + DirectoryHelper.DeleteIfExists(_testDirectoryPath, true); + } } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs index 195e51f335..b995e18785 100644 --- a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs +++ b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using System.Linq; using System.Threading.Tasks; using Shouldly; @@ -25,21 +24,53 @@ namespace Volo.Abp.BlobStoring options.UseAutofac(); } - [Fact] - public async Task SaveAsync() + [Theory] + [InlineData("test-blob-1")] + [InlineData("test-blob-1.txt")] + [InlineData("test-folder/test-blob-1")] + public async Task Should_Save_And_Get_Blobs(string blobName) { var testContent = "test content".GetBytes(); - - using (var memoryStream = new MemoryStream(testContent)) - { - await Container.SaveAsync("test-blob-1", memoryStream); - } + await Container.SaveAsync(blobName, testContent); - using (var stream = await Container.GetAsync("test-blob-1")) - { - var result = await stream.GetAllBytesAsync(); - result.SequenceEqual(testContent).ShouldBeTrue(); - } + var result = await Container.GetAllBytesAsync(blobName); + result.SequenceEqual(testContent).ShouldBeTrue(); + } + + [Theory] + [InlineData("test-blob-1")] + [InlineData("test-blob-1.txt")] + [InlineData("test-folder/test-blob-1")] + public async Task Should_Delete_Saved_Blobs(string blobName) + { + await Container.SaveAsync(blobName, "test content".GetBytes()); + (await Container.GetAllBytesAsync(blobName)).ShouldNotBeNull(); + + await Container.DeleteAsync(blobName); + (await Container.GetAllBytesOrNullAsync(blobName)).ShouldBeNull(); + } + + [Theory] + [InlineData("test-blob-1")] + [InlineData("test-blob-1.txt")] + [InlineData("test-folder/test-blob-1")] + public async Task Saved_Blobs_Should_Exists(string blobName) + { + await Container.SaveAsync(blobName, "test content".GetBytes()); + (await Container.ExistsAsync(blobName)).ShouldBeTrue(); + + await Container.DeleteAsync(blobName); + (await Container.ExistsAsync(blobName)).ShouldBeFalse(); + } + + [Theory] + [InlineData("test-blob-1")] + [InlineData("test-blob-1.txt")] + [InlineData("test-folder/test-blob-1")] + public async Task Unknown_Blobs_Should_Not_Exists(string blobName) + { + await Container.DeleteAsync(blobName); + (await Container.ExistsAsync(blobName)).ShouldBeFalse(); } } } \ No newline at end of file From ebf225822d3fa473967bd3d4784390064a97548f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Thu, 28 May 2020 06:58:46 +0300 Subject: [PATCH 18/20] Introduce BlobAlreadyExistsException --- .../FileSystem/FileSystemBlobProvider.cs | 18 +++++++---- .../BlobStoring/BlobAlreadyExistsException.cs | 31 +++++++++++++++++++ .../Abp/BlobStoring/BlobContainer_Tests.cs | 29 +++++++++++++++++ 3 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobAlreadyExistsException.cs diff --git a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs index 9194a78652..34be8c3eb3 100644 --- a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs @@ -6,7 +6,7 @@ using Volo.Abp.IO; namespace Volo.Abp.BlobStoring.FileSystem { //TODO: What if the file is being used on create, delete or read? - //TODO: Implement all methods truly async! + //TODO: Implement all methods truly async (if possible)! public class FileSystemBlobProvider : BlobProviderBase, ITransientDependency { @@ -20,6 +20,11 @@ namespace Volo.Abp.BlobStoring.FileSystem public override async Task SaveAsync(BlobProviderSaveArgs args) { var filePath = FilePathCalculator.Calculate(args); + + if (!args.OverrideExisting && await ExistsAsync(filePath)) + { + throw new BlobAlreadyExistsException($"Saving BLOB '{args.BlobName}' does already exists in the container '{args.ContainerName}'! Set {nameof(args.OverrideExisting)} if it should be overwritten."); + } DirectoryHelper.CreateIfNotExists(Path.GetDirectoryName(filePath)); @@ -29,8 +34,6 @@ namespace Volo.Abp.BlobStoring.FileSystem using (var fileStream = File.Open(filePath, fileMode, FileAccess.Write)) { - //TODO: Truely implement this (like this? http://writeasync.net/?p=2621 or https://www.infoworld.com/article/2995387/how-to-perform-asynchronous-file-operations-in-c.html) - await args.BlobStream.CopyToAsync( fileStream, args.CancellationToken @@ -43,15 +46,13 @@ namespace Volo.Abp.BlobStoring.FileSystem public override Task DeleteAsync(BlobProviderDeleteArgs args) { var filePath = FilePathCalculator.Calculate(args); - return Task.FromResult(FileHelper.DeleteIfExists(filePath)); } public override Task ExistsAsync(BlobProviderExistsArgs args) { var filePath = FilePathCalculator.Calculate(args); - - return Task.FromResult(File.Exists(filePath)); + return ExistsAsync(filePath); } public override Task GetOrNullAsync(BlobProviderGetArgs args) @@ -65,5 +66,10 @@ namespace Volo.Abp.BlobStoring.FileSystem return Task.FromResult(File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)); } + + protected virtual Task ExistsAsync(string filePath) + { + return Task.FromResult(File.Exists(filePath)); + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobAlreadyExistsException.cs b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobAlreadyExistsException.cs new file mode 100644 index 0000000000..51eaf29783 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobAlreadyExistsException.cs @@ -0,0 +1,31 @@ +using System; +using System.Runtime.Serialization; + +namespace Volo.Abp.BlobStoring +{ + public class BlobAlreadyExistsException : AbpException + { + public BlobAlreadyExistsException() + { + + } + + public BlobAlreadyExistsException(string message) + : base(message) + { + + } + + public BlobAlreadyExistsException(string message, Exception innerException) + : base(message, innerException) + { + + } + + public BlobAlreadyExistsException(SerializationInfo serializationInfo, StreamingContext context) + : base(serializationInfo, context) + { + + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs index b995e18785..091c1b7c95 100644 --- a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs +++ b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs @@ -36,6 +36,35 @@ namespace Volo.Abp.BlobStoring var result = await Container.GetAllBytesAsync(blobName); result.SequenceEqual(testContent).ShouldBeTrue(); } + + [Fact] + public async Task Should_Overwrite_Pre_Saved_Blob_If_Requested() + { + var blobName = "test-blob-1"; + + var testContent = "test content".GetBytes(); + await Container.SaveAsync(blobName, testContent); + + var testContentOverwritten = "test content overwritten".GetBytes(); + await Container.SaveAsync(blobName, testContentOverwritten, true); + + var result = await Container.GetAllBytesAsync(blobName); + result.SequenceEqual(testContentOverwritten).ShouldBeTrue(); + } + + [Fact] + public async Task Should_Not_Allow_To_Overwrite_Pre_Saved_Blob_By_Default() + { + var blobName = "test-blob-1"; + + var testContent = "test content".GetBytes(); + await Container.SaveAsync(blobName, testContent); + + var testContentOverwritten = "test content overwritten".GetBytes(); + await Assert.ThrowsAsync(() => + Container.SaveAsync(blobName, testContentOverwritten) + ); + } [Theory] [InlineData("test-blob-1")] From c3aeaefc40861d3b6ea0e2d14b813154128d5f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Thu, 28 May 2020 07:02:20 +0300 Subject: [PATCH 19/20] Delete TODOs created issue --- .../Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs index 34be8c3eb3..ef566f66c4 100644 --- a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs @@ -5,9 +5,6 @@ using Volo.Abp.IO; namespace Volo.Abp.BlobStoring.FileSystem { - //TODO: What if the file is being used on create, delete or read? - //TODO: Implement all methods truly async (if possible)! - public class FileSystemBlobProvider : BlobProviderBase, ITransientDependency { protected IBlogFilePathCalculator FilePathCalculator { get; } From f50fbcefa455f6ff479092b0d6bb7eaa95b6ae5c Mon Sep 17 00:00:00 2001 From: Ahmet Date: Thu, 28 May 2020 11:31:07 +0300 Subject: [PATCH 20/20] blobstroring - name fix --- ...FilePathCalculator.cs => DefaultBlobFilePathCalculator.cs} | 2 +- .../Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs | 4 ++-- ...{IBlogFilePathCalculator.cs => IBlobFilePathCalculator.cs} | 2 +- .../BlobStoring/FileSystem/BlogFilePathCalculator_Tests.cs | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) rename framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/{DefaultBlogFilePathCalculator.cs => DefaultBlobFilePathCalculator.cs} (93%) rename framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/{IBlogFilePathCalculator.cs => IBlobFilePathCalculator.cs} (70%) diff --git a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/DefaultBlogFilePathCalculator.cs b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/DefaultBlobFilePathCalculator.cs similarity index 93% rename from framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/DefaultBlogFilePathCalculator.cs rename to framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/DefaultBlobFilePathCalculator.cs index 62c2585375..021ecd814d 100644 --- a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/DefaultBlogFilePathCalculator.cs +++ b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/DefaultBlobFilePathCalculator.cs @@ -3,7 +3,7 @@ using Volo.Abp.DependencyInjection; namespace Volo.Abp.BlobStoring.FileSystem { - public class DefaultBlogFilePathCalculator : IBlogFilePathCalculator, ITransientDependency + public class DefaultBlobFilePathCalculator : IBlobFilePathCalculator, ITransientDependency { public virtual string Calculate(BlobProviderArgs args) { diff --git a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs index ef566f66c4..aafba5b696 100644 --- a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs @@ -7,9 +7,9 @@ namespace Volo.Abp.BlobStoring.FileSystem { public class FileSystemBlobProvider : BlobProviderBase, ITransientDependency { - protected IBlogFilePathCalculator FilePathCalculator { get; } + protected IBlobFilePathCalculator FilePathCalculator { get; } - public FileSystemBlobProvider(IBlogFilePathCalculator filePathCalculator) + public FileSystemBlobProvider(IBlobFilePathCalculator filePathCalculator) { FilePathCalculator = filePathCalculator; } diff --git a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/IBlogFilePathCalculator.cs b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/IBlobFilePathCalculator.cs similarity index 70% rename from framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/IBlogFilePathCalculator.cs rename to framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/IBlobFilePathCalculator.cs index 9e4ec4713a..2e7c6b551a 100644 --- a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/IBlogFilePathCalculator.cs +++ b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/IBlobFilePathCalculator.cs @@ -1,6 +1,6 @@ namespace Volo.Abp.BlobStoring.FileSystem { - public interface IBlogFilePathCalculator + public interface IBlobFilePathCalculator { string Calculate(BlobProviderArgs args); } diff --git a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/BlogFilePathCalculator_Tests.cs b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/BlogFilePathCalculator_Tests.cs index f7b55de401..cc68209790 100644 --- a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/BlogFilePathCalculator_Tests.cs +++ b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/BlogFilePathCalculator_Tests.cs @@ -7,11 +7,11 @@ namespace Volo.Abp.BlobStoring.FileSystem { public class BlogFilePathCalculator_Tests : AbpBlobStoringFileSystemTestBase { - private readonly IBlogFilePathCalculator _calculator; + private readonly IBlobFilePathCalculator _calculator; public BlogFilePathCalculator_Tests() { - _calculator = GetRequiredService(); + _calculator = GetRequiredService(); } [Fact]