WebFileServer20
Changes
Src/Tools.Identity.EF/BaseIdentityContext.cs 112(+112 -0)
Src/Tools.Identity.EF/Entities/BaseRole.cs 47(+47 -0)
Src/Tools.Identity.EF/Entities/BaseUser.cs 45(+45 -0)
Src/WebFileServ.Model.DI/DIManager.cs 28(+10 -18)
Src/WebFileServ.sln 21(+14 -7)
Details
Src/Tools.Identity.EF/BaseIdentityContext.cs 112(+112 -0)
diff --git a/Src/Tools.Identity.EF/BaseIdentityContext.cs b/Src/Tools.Identity.EF/BaseIdentityContext.cs
new file mode 100644
index 0000000..42f0747
--- /dev/null
+++ b/Src/Tools.Identity.EF/BaseIdentityContext.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Options;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
+
+using IdentityServer4.EntityFramework.Entities;
+using IdentityServer4.EntityFramework.Extensions;
+using IdentityServer4.EntityFramework.Interfaces;
+using IdentityServer4.EntityFramework.Options;
+
+
+using Tools.Identity.EF.Entities;
+
+namespace Tools.Identity.EF
+{
+
+#warning Подходит только для Identity Server 3.*
+
+ /// <summary>
+ /// Database abstraction for a combined <see cref="DbContext"/> using ASP.NET Identity and Identity Server.
+ /// Данный контекст используется для работы Identity и IndetityServer
+ /// </summary>
+ /// <typeparam name="TUser"></typeparam>
+ /// <typeparam name="TRole"></typeparam>
+ /// <typeparam name="TKey">Key of the IdentityUser entity</typeparam>
+ public class BaseIdentityContext<TKey, TUser, TRole, TUserRole>
+ :
+ IdentityDbContext<
+ TUser,
+ TRole,
+ TKey,
+ IdentityUserClaim<TKey>,
+ BaseUserRole<TKey, TUser, TRole>,
+ IdentityUserLogin<TKey>,
+ IdentityRoleClaim<TKey>,
+ IdentityUserToken<TKey>
+ >,
+ IPersistedGrantDbContext
+
+ where TKey : IEquatable<TKey>
+ where TUser : BaseUser<TKey, TUser, TRole>
+ where TRole : BaseRole<TKey, TUser, TRole>
+ where TUserRole : BaseUserRole<TKey, TUser, TRole>
+
+ {
+ private readonly IOptions<OperationalStoreOptions> _operationalStoreOptions;
+
+
+ /// <summary>
+ /// Initializes a new instance of <see cref="ApiAuthorizationDbContext{TUser, TRole, TKey}"/>.
+ /// </summary>
+ /// <param name="options">The <see cref="DbContextOptions"/>.</param>
+ /// <param name="operationalStoreOptions">The <see cref="IOptions{OperationalStoreOptions}"/>.</param>
+ public BaseIdentityContext
+ (
+ DbContextOptions options,
+ IOptions<OperationalStoreOptions> operationalStoreOptions
+ )
+ : base(options)
+ {
+ _operationalStoreOptions = operationalStoreOptions;
+ }
+
+
+ #region IPersistedGrantDbContext
+
+ /// <summary>
+ /// Gets or sets the <see cref="DbSet{PersistedGrant}"/>.
+ /// </summary>
+ public DbSet<PersistedGrant> PersistedGrants { get; set; }
+
+ /// <summary>
+ /// Gets or sets the <see cref="DbSet{DeviceFlowCodes}"/>.
+ /// </summary>
+ public DbSet<DeviceFlowCodes> DeviceFlowCodes { get; set; }
+
+ Task<int> IPersistedGrantDbContext.SaveChangesAsync()
+ => base.SaveChangesAsync();
+
+ #endregion
+
+ /// <inheritdoc />
+ protected override void OnModelCreating(ModelBuilder builder)
+ {
+ base.OnModelCreating(builder);
+
+ builder
+ .ConfigurePersistedGrantContext(_operationalStoreOptions.Value);
+
+ //builder.Entity<UserRole<TKey, TUser, TRole>>()
+ // .HasKey(t => new { t.UserId, t.RoleId });
+
+ builder.Entity<BaseUserRole<TKey, TUser, TRole>>()
+ .HasOne(sc => sc.User)
+ .WithMany(s => s.Roles)
+ .HasForeignKey(sc => sc.UserId)
+ .IsRequired();
+
+ builder.Entity<BaseUserRole<TKey, TUser, TRole>>()
+ .HasOne(sc => sc.Role)
+ .WithMany(c => c.Users)
+ .HasForeignKey(sc => sc.RoleId)
+ .IsRequired();
+ }
+ }
+
+}
Src/Tools.Identity.EF/Entities/BaseRole.cs 47(+47 -0)
diff --git a/Src/Tools.Identity.EF/Entities/BaseRole.cs b/Src/Tools.Identity.EF/Entities/BaseRole.cs
new file mode 100644
index 0000000..0b78536
--- /dev/null
+++ b/Src/Tools.Identity.EF/Entities/BaseRole.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Linq;
+using System.ComponentModel.DataAnnotations.Schema;
+
+using Microsoft.AspNetCore.Identity;
+
+namespace Tools.Identity.EF.Entities
+{
+ public class BaseRole<TKey, TUser, TRole>
+ : IdentityRole<TKey>
+
+ where TKey : IEquatable<TKey>
+ where TUser : BaseUser<TKey, TUser, TRole>
+ where TRole : BaseRole<TKey, TUser, TRole>
+ {
+ public virtual List<BaseUserRole<TKey, TUser, TRole>> Users { set; get; }
+
+
+ [NotMapped]
+ public IReadOnlyDictionary<TKey, TUser> UsersDict
+ {
+ get => Users
+ .ToDictionary(e => e.UserId, e => e.User);
+ set => Users = value
+ .Select(
+ e => new BaseUserRole<TKey, TUser, TRole>()
+ {
+ UserId = e.Key,
+ User = e.Value,
+
+ RoleId = Id,
+ Role = (TRole)this
+ }
+ )
+ .ToList();
+ }
+
+
+
+ public BaseRole() { }
+ public BaseRole(string roleName)
+ : base(roleName) { }
+ }
+
+}
Src/Tools.Identity.EF/Entities/BaseUser.cs 45(+45 -0)
diff --git a/Src/Tools.Identity.EF/Entities/BaseUser.cs b/Src/Tools.Identity.EF/Entities/BaseUser.cs
new file mode 100644
index 0000000..38048a4
--- /dev/null
+++ b/Src/Tools.Identity.EF/Entities/BaseUser.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Text;
+
+using System.ComponentModel.DataAnnotations.Schema;
+
+using Microsoft.AspNetCore.Identity;
+
+namespace Tools.Identity.EF.Entities
+{
+ public class BaseUser<TKey, TUser, TRole>
+ : IdentityUser<TKey>
+
+ where TKey : IEquatable<TKey>
+ where TUser : BaseUser<TKey, TUser, TRole>
+ where TRole : BaseRole<TKey, TUser, TRole>
+ {
+ public virtual List<BaseUserRole<TKey, TUser, TRole>> Roles { set; get; }
+
+
+ [NotMapped]
+ public IReadOnlyDictionary<TKey, TRole> RolesDict
+ {
+ get => Roles
+ .ToDictionary(e => e.RoleId, e => e.Role);
+ set => Roles = value
+ .Select(
+ e => new BaseUserRole<TKey, TUser, TRole>()
+ {
+ UserId = Id,
+ User = (TUser)this,
+
+ RoleId = e.Key,
+ Role = e.Value
+ }
+ )
+ .ToList();
+ }
+
+
+ public BaseUser() { }
+ }
+
+}
diff --git a/Src/Tools.Identity.EF/Entities/BaseUserRole.cs b/Src/Tools.Identity.EF/Entities/BaseUserRole.cs
new file mode 100644
index 0000000..6d69bb5
--- /dev/null
+++ b/Src/Tools.Identity.EF/Entities/BaseUserRole.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using Microsoft.AspNetCore.Identity;
+
+namespace Tools.Identity.EF.Entities
+{
+ public class BaseUserRole<TKey, TUser, TRole>
+ : IdentityUserRole<TKey>
+
+ where TKey : IEquatable<TKey>
+ where TUser : BaseUser<TKey, TUser, TRole>
+ where TRole : BaseRole<TKey, TUser, TRole>
+ {
+ public virtual TUser User { get; set; }
+
+ public virtual TRole Role { get; set; }
+ }
+
+}
diff --git a/Src/Tools.Identity.EF/Tools.Identity.EF.csproj b/Src/Tools.Identity.EF/Tools.Identity.EF.csproj
new file mode 100644
index 0000000..f6f12c2
--- /dev/null
+++ b/Src/Tools.Identity.EF/Tools.Identity.EF.csproj
@@ -0,0 +1,14 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>netcoreapp3.1</TargetFramework>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="IdentityServer4" Version="3.1.4" />
+ <PackageReference Include="IdentityServer4.EntityFramework" Version="3.1.4" />
+ <PackageReference Include="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="3.1.9" />
+ <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.9" />
+ </ItemGroup>
+
+</Project>
diff --git a/Src/WebFileServ.Model.DAL/DataBase/EF/ApplicationDbContext.cs b/Src/WebFileServ.Model.DAL/DataBase/EF/ApplicationDbContext.cs
index 78d2098..20b9958 100644
--- a/Src/WebFileServ.Model.DAL/DataBase/EF/ApplicationDbContext.cs
+++ b/Src/WebFileServ.Model.DAL/DataBase/EF/ApplicationDbContext.cs
@@ -5,19 +5,24 @@ using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
+//using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
+//using Microsoft.AspNetCore.ApiAuthorization.IdentityServer;
using IdentityServer4.EntityFramework.Options;
-using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
-
-using Microsoft.AspNetCore.ApiAuthorization.IdentityServer;
+using Tools.Identity.EF;
using WebFileServ.Model.Entities.Identity;
namespace WebFileServ.Model.DAL.DataBase.EF
{
public class ApplicationDbContext
- : ApiAuthorizationDbContext<ApplicationUser>
+ : BaseIdentityContext<
+ Guid,
+ ApplicationUser,
+ ApplicationRole,
+ ApplicationUserRole
+ >
{
public ApplicationDbContext(
@@ -38,6 +43,7 @@ namespace WebFileServ.Model.DAL.DataBase.EF
//Microsoft.EntityFrameworkCore.Proxies
.UseLazyLoadingProxies();
+
base.OnConfiguring(optionsBuilder);
}
diff --git a/Src/WebFileServ.Model.DAL/DataInit/DataInitializer.cs b/Src/WebFileServ.Model.DAL/DataInit/DataInitializer.cs
index 1090cb3..df782ca 100644
--- a/Src/WebFileServ.Model.DAL/DataInit/DataInitializer.cs
+++ b/Src/WebFileServ.Model.DAL/DataInit/DataInitializer.cs
@@ -24,7 +24,7 @@ namespace WebFileServ.Model.DAL.DataInit
private readonly ApplicationDbContext Context;
private readonly UserManager<ApplicationUser> UserManager;
- private readonly RoleManager<IdentityRole> RoleManager;
+ private readonly RoleManager<ApplicationRole> RoleManager;
@@ -32,14 +32,17 @@ namespace WebFileServ.Model.DAL.DataInit
public DataInitializer
(
DataInitializerConfig dataInitializerConfig,
+
ApplicationDbContext context,
+
UserManager<ApplicationUser> userManager,
- RoleManager<IdentityRole> roleManager
+ RoleManager<ApplicationRole> roleManager
)
{
DataInitializerConfig = dataInitializerConfig;
Context = context;
+
UserManager = userManager;
RoleManager = roleManager;
}
@@ -102,7 +105,7 @@ namespace WebFileServ.Model.DAL.DataInit
if (adminRole == null)
{
var createRoleResult = await RoleManager.CreateAsync(
- new IdentityRole(roleName)
+ new ApplicationRole(roleName)
);
if (!createRoleResult.Succeeded)
@@ -136,7 +139,6 @@ namespace WebFileServ.Model.DAL.DataInit
);
}
-
adminUser = await UserManager
.FindByNameAsync(email);
@@ -149,6 +151,9 @@ namespace WebFileServ.Model.DAL.DataInit
addToRoleResult.Errors.FirstOrDefault()?.Description
);
}
+
+ var adminRoles = adminUser
+ .RolesDict;
}
}
diff --git a/Src/WebFileServ.Model.DAL/Migrations/ApplicationDbContextModelSnapshot.cs b/Src/WebFileServ.Model.DAL/Migrations/ApplicationDbContextModelSnapshot.cs
index 287ecc0..89353d1 100644
--- a/Src/WebFileServ.Model.DAL/Migrations/ApplicationDbContextModelSnapshot.cs
+++ b/Src/WebFileServ.Model.DAL/Migrations/ApplicationDbContextModelSnapshot.cs
@@ -101,34 +101,7 @@ namespace WebFileServ.Model.DAL.Migrations
b.ToTable("PersistedGrants");
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
- {
- b.Property<string>("Id")
- .HasColumnType("nvarchar(450)");
-
- b.Property<string>("ConcurrencyStamp")
- .IsConcurrencyToken()
- .HasColumnType("nvarchar(max)");
-
- b.Property<string>("Name")
- .HasColumnType("nvarchar(256)")
- .HasMaxLength(256);
-
- b.Property<string>("NormalizedName")
- .HasColumnType("nvarchar(256)")
- .HasMaxLength(256);
-
- b.HasKey("Id");
-
- b.HasIndex("NormalizedName")
- .IsUnique()
- .HasName("RoleNameIndex")
- .HasFilter("[NormalizedName] IS NOT NULL");
-
- b.ToTable("AspNetRoles");
- });
-
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@@ -141,9 +114,8 @@ namespace WebFileServ.Model.DAL.Migrations
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
- b.Property<string>("RoleId")
- .IsRequired()
- .HasColumnType("nvarchar(450)");
+ b.Property<Guid>("RoleId")
+ .HasColumnType("uniqueidentifier");
b.HasKey("Id");
@@ -152,7 +124,7 @@ namespace WebFileServ.Model.DAL.Migrations
b.ToTable("AspNetRoleClaims");
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@@ -165,9 +137,8 @@ namespace WebFileServ.Model.DAL.Migrations
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
- b.Property<string>("UserId")
- .IsRequired()
- .HasColumnType("nvarchar(450)");
+ b.Property<Guid>("UserId")
+ .HasColumnType("uniqueidentifier");
b.HasKey("Id");
@@ -176,7 +147,7 @@ namespace WebFileServ.Model.DAL.Migrations
b.ToTable("AspNetUserClaims");
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(128)")
@@ -189,9 +160,8 @@ namespace WebFileServ.Model.DAL.Migrations
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
- b.Property<string>("UserId")
- .IsRequired()
- .HasColumnType("nvarchar(450)");
+ b.Property<Guid>("UserId")
+ .HasColumnType("uniqueidentifier");
b.HasKey("LoginProvider", "ProviderKey");
@@ -200,13 +170,34 @@ namespace WebFileServ.Model.DAL.Migrations
b.ToTable("AspNetUserLogins");
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
+ {
+ b.Property<Guid>("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("LoginProvider")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property<string>("Name")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property<string>("Value")
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("UserId", "LoginProvider", "Name");
+
+ b.ToTable("AspNetUserTokens");
+ });
+
+ modelBuilder.Entity("Tools.Identity.EF.Entities.BaseUserRole<System.Guid, WebFileServ.Model.Entities.Identity.ApplicationUser, WebFileServ.Model.Entities.Identity.ApplicationRole>", b =>
{
- b.Property<string>("UserId")
- .HasColumnType("nvarchar(450)");
+ b.Property<Guid>("UserId")
+ .HasColumnType("uniqueidentifier");
- b.Property<string>("RoleId")
- .HasColumnType("nvarchar(450)");
+ b.Property<Guid>("RoleId")
+ .HasColumnType("uniqueidentifier");
b.HasKey("UserId", "RoleId");
@@ -215,31 +206,39 @@ namespace WebFileServ.Model.DAL.Migrations
b.ToTable("AspNetUserRoles");
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
+ modelBuilder.Entity("WebFileServ.Model.Entities.Identity.ApplicationRole", b =>
{
- b.Property<string>("UserId")
- .HasColumnType("nvarchar(450)");
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
- b.Property<string>("LoginProvider")
- .HasColumnType("nvarchar(128)")
- .HasMaxLength(128);
+ b.Property<string>("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnType("nvarchar(max)");
b.Property<string>("Name")
- .HasColumnType("nvarchar(128)")
- .HasMaxLength(128);
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
- b.Property<string>("Value")
- .HasColumnType("nvarchar(max)");
+ b.Property<string>("NormalizedName")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
- b.HasKey("UserId", "LoginProvider", "Name");
+ b.HasKey("Id");
- b.ToTable("AspNetUserTokens");
+ b.HasIndex("NormalizedName")
+ .IsUnique()
+ .HasName("RoleNameIndex")
+ .HasFilter("[NormalizedName] IS NOT NULL");
+
+ b.ToTable("AspNetRoles");
});
modelBuilder.Entity("WebFileServ.Model.Entities.Identity.ApplicationUser", b =>
{
- b.Property<string>("Id")
- .HasColumnType("nvarchar(450)");
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
@@ -301,16 +300,16 @@ namespace WebFileServ.Model.DAL.Migrations
b.ToTable("AspNetUsers");
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b =>
{
- b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
+ b.HasOne("WebFileServ.Model.Entities.Identity.ApplicationRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
{
b.HasOne("WebFileServ.Model.Entities.Identity.ApplicationUser", null)
.WithMany()
@@ -319,7 +318,7 @@ namespace WebFileServ.Model.DAL.Migrations
.IsRequired();
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
{
b.HasOne("WebFileServ.Model.Entities.Identity.ApplicationUser", null)
.WithMany()
@@ -328,14 +327,8 @@ namespace WebFileServ.Model.DAL.Migrations
.IsRequired();
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
{
- b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
- .WithMany()
- .HasForeignKey("RoleId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
b.HasOne("WebFileServ.Model.Entities.Identity.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
@@ -343,10 +336,16 @@ namespace WebFileServ.Model.DAL.Migrations
.IsRequired();
});
- modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
+ modelBuilder.Entity("Tools.Identity.EF.Entities.BaseUserRole<System.Guid, WebFileServ.Model.Entities.Identity.ApplicationUser, WebFileServ.Model.Entities.Identity.ApplicationRole>", b =>
{
- b.HasOne("WebFileServ.Model.Entities.Identity.ApplicationUser", null)
- .WithMany()
+ b.HasOne("WebFileServ.Model.Entities.Identity.ApplicationRole", "Role")
+ .WithMany("Users")
+ .HasForeignKey("RoleId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("WebFileServ.Model.Entities.Identity.ApplicationUser", "User")
+ .WithMany("Roles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
diff --git a/Src/WebFileServ.Model.DAL/WebFileServ.Model.DAL.csproj b/Src/WebFileServ.Model.DAL/WebFileServ.Model.DAL.csproj
index e34105d..7e248e8 100644
--- a/Src/WebFileServ.Model.DAL/WebFileServ.Model.DAL.csproj
+++ b/Src/WebFileServ.Model.DAL/WebFileServ.Model.DAL.csproj
@@ -1,11 +1,10 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="3.1.9" />
<PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="3.1.9" />
@@ -17,7 +16,12 @@
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="..\Tools.Identity.EF\Tools.Identity.EF.csproj" />
<ProjectReference Include="..\WebFileServ.Model.Entities\WebFileServ.Model.Entities.csproj" />
</ItemGroup>
+ <ItemGroup>
+ <Folder Include="Migrations\" />
+ </ItemGroup>
+
</Project>
Src/WebFileServ.Model.DI/DIManager.cs 28(+10 -18)
diff --git a/Src/WebFileServ.Model.DI/DIManager.cs b/Src/WebFileServ.Model.DI/DIManager.cs
index 65eb889..55a6e74 100644
--- a/Src/WebFileServ.Model.DI/DIManager.cs
+++ b/Src/WebFileServ.Model.DI/DIManager.cs
@@ -50,7 +50,7 @@ namespace WebFileServ.Model.DI
RegistryDAL(services, configuration);
- RegustryIdentity(services, configuration);
+ RegistryIdentity(services, configuration);
RegistryBLL(services, configuration);
}
@@ -61,31 +61,21 @@ namespace WebFileServ.Model.DI
{
services
.AddSingleton(configuration);
- services
- .AddSingleton<DataInitializerConfig>();
-
- //if (Enviroment == EnumEnviroment.WebApp)
- //{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
configuration.GetConnectionString("DefaultConnection")
)
);
- //}
- //else
- //{
- // services.AddDbContext<ApplicationDbContext>(options =>
- // options.UseInMemoryDatabase("TestDb")
- // );
- //}
+
services
+ .AddSingleton<DataInitializerConfig>()
.AddScoped<DataInitializer>();
}
- private void RegustryIdentity(IServiceCollection services, IConfiguration configuration)
+ private void RegistryIdentity(IServiceCollection services, IConfiguration configuration)
{
if (Enviroment != AppEnviroment.UnitTests)
{
@@ -105,12 +95,14 @@ namespace WebFileServ.Model.DI
RequireNonAlphanumeric = false
};
}
- )
- .AddRoles<IdentityRole>()
+ )
+ .AddRoles<ApplicationRole>()
+ .AddRoleManager<RoleManager<ApplicationRole>>()
.AddEntityFrameworkStores<ApplicationDbContext>();
- services.AddIdentityServer()
- .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
+ services
+ .AddIdentityServer()
+ .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
}
}
diff --git a/Src/WebFileServ.Model.Entities/Identity/ApplicationRole.cs b/Src/WebFileServ.Model.Entities/Identity/ApplicationRole.cs
new file mode 100644
index 0000000..0bcf276
--- /dev/null
+++ b/Src/WebFileServ.Model.Entities/Identity/ApplicationRole.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+using Tools.Identity.EF.Entities;
+
+namespace WebFileServ.Model.Entities.Identity
+{
+ public class ApplicationRole
+ : BaseRole<
+ Guid,
+ ApplicationUser,
+ ApplicationRole
+ >
+ {
+
+ public ApplicationRole()
+ { }
+ public ApplicationRole(string roleName)
+ : base(roleName)
+ { }
+ }
+
+}
diff --git a/Src/WebFileServ.Model.Entities/Identity/ApplicationUser.cs b/Src/WebFileServ.Model.Entities/Identity/ApplicationUser.cs
index 8dfc2f6..719216f 100644
--- a/Src/WebFileServ.Model.Entities/Identity/ApplicationUser.cs
+++ b/Src/WebFileServ.Model.Entities/Identity/ApplicationUser.cs
@@ -3,14 +3,17 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.Identity;
+using Tools.Identity.EF.Entities;
namespace WebFileServ.Model.Entities.Identity
{
- public class ApplicationUser
- : IdentityUser
- {
-
+ public class ApplicationUser
+ : BaseUser<
+ Guid,
+ ApplicationUser,
+ ApplicationRole
+ >
+ {
}
}
diff --git a/Src/WebFileServ.Model.Entities/Identity/ApplicationUserRole.cs b/Src/WebFileServ.Model.Entities/Identity/ApplicationUserRole.cs
new file mode 100644
index 0000000..7f2cd63
--- /dev/null
+++ b/Src/WebFileServ.Model.Entities/Identity/ApplicationUserRole.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+using Tools.Identity.EF.Entities;
+
+namespace WebFileServ.Model.Entities.Identity
+{
+ public class ApplicationUserRole
+ : BaseUserRole<
+ Guid,
+ ApplicationUser,
+ ApplicationRole
+ >
+ {
+ }
+
+}
diff --git a/Src/WebFileServ.Model.Entities/WebFileServ.Model.Entities.csproj b/Src/WebFileServ.Model.Entities/WebFileServ.Model.Entities.csproj
index 7d17a3f..b75481f 100644
--- a/Src/WebFileServ.Model.Entities/WebFileServ.Model.Entities.csproj
+++ b/Src/WebFileServ.Model.Entities/WebFileServ.Model.Entities.csproj
@@ -9,4 +9,8 @@
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="3.1.9" />
</ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Tools.Identity.EF\Tools.Identity.EF.csproj" />
+ </ItemGroup>
+
</Project>
Src/WebFileServ.sln 21(+14 -7)
diff --git a/Src/WebFileServ.sln b/Src/WebFileServ.sln
index 6dcc67a..8ac57cd 100644
--- a/Src/WebFileServ.sln
+++ b/Src/WebFileServ.sln
@@ -9,21 +9,23 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Model", "Model", "{883FD108
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{B9C7B869-94B9-445C-80FD-17E0A601A303}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebFileServ.Model.Entities", "WebFileServ.Model.Entities\WebFileServ.Model.Entities.csproj", "{905AAC41-34C7-43DB-8AB4-58970EFEC5ED}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebFileServ.Model.Entities", "WebFileServ.Model.Entities\WebFileServ.Model.Entities.csproj", "{905AAC41-34C7-43DB-8AB4-58970EFEC5ED}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebFileServ.Model.DAL", "WebFileServ.Model.DAL\WebFileServ.Model.DAL.csproj", "{B701142C-9BF3-4F15-96D9-50017F0A36BC}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebFileServ.Model.DAL", "WebFileServ.Model.DAL\WebFileServ.Model.DAL.csproj", "{B701142C-9BF3-4F15-96D9-50017F0A36BC}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebFileServ.WebApp", "WebFileServ.WebApp\WebFileServ.WebApp.csproj", "{E34E770C-A485-4EE1-AD18-1A5665C368D9}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebFileServ.WebApp", "WebFileServ.WebApp\WebFileServ.WebApp.csproj", "{E34E770C-A485-4EE1-AD18-1A5665C368D9}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebFileServ.Test", "WebFileServ.Test", "{FDB98DA0-4EFD-4DDC-A01D-6A9A2C21A5F9}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebFileServ.Model.DI", "WebFileServ.Model.DI\WebFileServ.Model.DI.csproj", "{D2B916A2-2F5D-4D83-8259-09561FA8A22B}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebFileServ.Model.DI", "WebFileServ.Model.DI\WebFileServ.Model.DI.csproj", "{D2B916A2-2F5D-4D83-8259-09561FA8A22B}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebFileServ.Test.ConsoleTest", "WebFileServ.Test.ConsoleTest\WebFileServ.Test.ConsoleTest.csproj", "{D7E4DD6B-17F1-488B-B9F6-533BB31B2DD7}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebFileServ.Test.ConsoleTest", "WebFileServ.Test.ConsoleTest\WebFileServ.Test.ConsoleTest.csproj", "{D7E4DD6B-17F1-488B-B9F6-533BB31B2DD7}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebFileServ.Model.BLL", "WebFileServ.Model.BLL\WebFileServ.Model.BLL.csproj", "{7F419249-7F5C-4D09-926E-8867BF52C5D2}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebFileServ.Model.BLL", "WebFileServ.Model.BLL\WebFileServ.Model.BLL.csproj", "{7F419249-7F5C-4D09-926E-8867BF52C5D2}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebFileServ.Test.UnitTests", "WebFileServ.Test.UnitTests\WebFileServ.Test.UnitTests.csproj", "{2A8D425B-0426-4C6F-AA33-59C36F543B10}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebFileServ.Test.UnitTests", "WebFileServ.Test.UnitTests\WebFileServ.Test.UnitTests.csproj", "{2A8D425B-0426-4C6F-AA33-59C36F543B10}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tools.Identity.EF", "Tools.Identity.EF\Tools.Identity.EF.csproj", "{7D3E7E6A-D523-4F52-9460-6C82F19A6E5C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -59,6 +61,10 @@ Global
{2A8D425B-0426-4C6F-AA33-59C36F543B10}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A8D425B-0426-4C6F-AA33-59C36F543B10}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2A8D425B-0426-4C6F-AA33-59C36F543B10}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7D3E7E6A-D523-4F52-9460-6C82F19A6E5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7D3E7E6A-D523-4F52-9460-6C82F19A6E5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7D3E7E6A-D523-4F52-9460-6C82F19A6E5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7D3E7E6A-D523-4F52-9460-6C82F19A6E5C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -72,6 +78,7 @@ Global
{D7E4DD6B-17F1-488B-B9F6-533BB31B2DD7} = {FDB98DA0-4EFD-4DDC-A01D-6A9A2C21A5F9}
{7F419249-7F5C-4D09-926E-8867BF52C5D2} = {883FD108-87F4-4E87-A222-780B037244AD}
{2A8D425B-0426-4C6F-AA33-59C36F543B10} = {FDB98DA0-4EFD-4DDC-A01D-6A9A2C21A5F9}
+ {7D3E7E6A-D523-4F52-9460-6C82F19A6E5C} = {B9C7B869-94B9-445C-80FD-17E0A601A303}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {540CF309-C759-4844-9BEA-596512586550}
diff --git a/Src/WebFileServ.Test.UnitTests/DITest.cs b/Src/WebFileServ.Test.UnitTests/DITest.cs
index 479c817..61ae5bb 100644
--- a/Src/WebFileServ.Test.UnitTests/DITest.cs
+++ b/Src/WebFileServ.Test.UnitTests/DITest.cs
@@ -7,6 +7,8 @@ using Microsoft.Extensions.Configuration;
using WebFileServ.Model.DI;
+using WebFileServ.Model.DAL.DataInit;
+
using WebFileServ.Model.BLL;
namespace WebFileServ.Test.UnitTests
@@ -49,5 +51,6 @@ namespace WebFileServ.Test.UnitTests
throw new Exception();
}
}
+
}
}
diff --git a/Src/WebFileServ.WebApp/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs b/Src/WebFileServ.WebApp/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs
index bdf8298..35b4eb5 100644
--- a/Src/WebFileServ.WebApp/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs
+++ b/Src/WebFileServ.WebApp/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs
@@ -87,7 +87,7 @@ namespace WebFileServ.WebApp.Areas.Identity.Pages.Account.Manage
return NotFound($"Unable to load user with ID 'user.Id'.");
}
- var info = await _signInManager.GetExternalLoginInfoAsync(user.Id);
+ var info = await _signInManager.GetExternalLoginInfoAsync(user.Id.ToString());
if (info == null)
{
throw new InvalidOperationException($"Unexpected error occurred loading external login info for user with ID '{user.Id}'.");
diff --git a/Src/WebFileServ.WebApp/Areas/Identity/Pages/Account/Manage/Index.cshtml b/Src/WebFileServ.WebApp/Areas/Identity/Pages/Account/Manage/Index.cshtml
index e018437..7dc76a0 100644
--- a/Src/WebFileServ.WebApp/Areas/Identity/Pages/Account/Manage/Index.cshtml
+++ b/Src/WebFileServ.WebApp/Areas/Identity/Pages/Account/Manage/Index.cshtml
@@ -20,6 +20,13 @@
<input asp-for="Input.PhoneNumber" class="form-control" />
<span asp-validation-for="Input.PhoneNumber" class="text-danger"></span>
</div>
+ <div class="form-group">
+ <label asp-for="UserRoles"></label>
+ @foreach (var item in Model.UserRoles)
+ {
+ <input asp-for=@item class="form-control" disabled/>
+ }
+ </div>
<button id="update-profile-button" type="submit" class="btn btn-primary">Save</button>
</form>
</div>
diff --git a/Src/WebFileServ.WebApp/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs b/Src/WebFileServ.WebApp/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs
index fac82d5..d27ce9d 100644
--- a/Src/WebFileServ.WebApp/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs
+++ b/Src/WebFileServ.WebApp/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs
@@ -12,44 +12,40 @@ namespace WebFileServ.WebApp.Areas.Identity.Pages.Account.Manage
{
public partial class IndexModel : PageModel
{
+ public class InputModel
+ {
+ [Phone]
+ [Display(Name = "Phone number")]
+ public string PhoneNumber { get; set; }
+ }
+
+
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
- public IndexModel(
- UserManager<ApplicationUser> userManager,
- SignInManager<ApplicationUser> signInManager)
- {
- _userManager = userManager;
- _signInManager = signInManager;
- }
public string Username { get; set; }
+ public string[] UserRoles { get; set; }
+
+
[TempData]
public string StatusMessage { get; set; }
[BindProperty]
public InputModel Input { get; set; }
- public class InputModel
- {
- [Phone]
- [Display(Name = "Phone number")]
- public string PhoneNumber { get; set; }
- }
- private async Task LoadAsync(ApplicationUser user)
+ public IndexModel(
+ UserManager<ApplicationUser> userManager,
+ SignInManager<ApplicationUser> signInManager)
{
- var userName = await _userManager.GetUserNameAsync(user);
- var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
+ _userManager = userManager;
+ _signInManager = signInManager;
+ }
- Username = userName;
- Input = new InputModel
- {
- PhoneNumber = phoneNumber
- };
- }
+ #region public
public async Task<IActionResult> OnGetAsync()
{
@@ -92,5 +88,28 @@ namespace WebFileServ.WebApp.Areas.Identity.Pages.Account.Manage
StatusMessage = "Your profile has been updated";
return RedirectToPage();
}
+
+ #endregion
+
+
+ private async Task LoadAsync(ApplicationUser user)
+ {
+ var userName = await _userManager.GetUserNameAsync(user);
+ var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
+ var userRoles = user
+ .Roles
+ .Select(e => e.Role.Name)
+ .ToArray();
+
+
+ Username = userName;
+ UserRoles = userRoles;
+
+ Input = new InputModel
+ {
+ PhoneNumber = phoneNumber
+ };
+ }
+
}
}
diff --git a/Src/WebFileServ.WebApp/WebFileServ.WebApp.csproj b/Src/WebFileServ.WebApp/WebFileServ.WebApp.csproj
index 7341d7b..ff476d3 100644
--- a/Src/WebFileServ.WebApp/WebFileServ.WebApp.csproj
+++ b/Src/WebFileServ.WebApp/WebFileServ.WebApp.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
+<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
@@ -17,10 +17,11 @@
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.9" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.1.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.9" />
- <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.9" />
- <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.9" />
- <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.9" />
+ <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.9">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.4" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
</ItemGroup>