strip jwt auth, no longer needed

This commit is contained in:
code liturgy 2022-11-18 00:33:03 +00:00
parent bd24e655ca
commit 7091849e38
14 changed files with 1143 additions and 336 deletions

View File

@ -14,7 +14,6 @@ namespace CodeLiturgy.Data.Auth.Context.Users
{ {
private readonly ApplicationUserManager _userManager; private readonly ApplicationUserManager _userManager;
private readonly IHasher _hasher; private readonly IHasher _hasher;
private readonly IJwtFactory _jwtFactory;
/// <summary> /// <summary>
/// Auth manager constructor /// Auth manager constructor
@ -25,12 +24,10 @@ namespace CodeLiturgy.Data.Auth.Context.Users
/// <param name="sessionCache"></param> /// <param name="sessionCache"></param>
public AuthManager( public AuthManager(
ApplicationUserManager userManager, ApplicationUserManager userManager,
IHasher hasher, IHasher hasher)
IJwtFactory jwtFactory)
{ {
_userManager = userManager; _userManager = userManager;
_hasher = hasher; _hasher = hasher;
_jwtFactory = jwtFactory;
} }
@ -41,17 +38,6 @@ namespace CodeLiturgy.Data.Auth.Context.Users
} }
private async Task<(bool, string)> GenerateBearerToken(ClaimsIdentity identity, ApplicationUser user)
{
var jwtToken = await _jwtFactory.GenerateEncodedToken(user.Id, user.UserName);
var completed = await _userManager.SetAuthenticationTokenAsync(user, SessionConstants.ApiNamePolicy,
SessionConstants.ApiNamePolicy, jwtToken.Token);
return (completed == IdentityResult.Success, jwtToken.Token);
}
/// <summary> /// <summary>
/// Verify Password /// Verify Password
/// </summary> /// </summary>

View File

@ -1,9 +0,0 @@
using System.Threading.Tasks;
using CodeLiturgy.Data.Application.Users;
namespace CodeLiturgy.Data.Auth.Context.Users;
public interface IJwtFactory
{
Task<AccessToken> GenerateEncodedToken(string id, string userName);
}

View File

@ -1,12 +0,0 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
namespace CodeLiturgy.Data.Auth.Context.Users
{
public interface IJwtTokenHandler
{
string WriteToken(JwtSecurityToken jwt);
ClaimsPrincipal ValidateToken(string token, TokenValidationParameters tokenValidationParameters);
}
}

View File

@ -1,85 +0,0 @@
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Principal;
using CodeLiturgy.Data.Application.Users;
using Microsoft.Extensions.Options;
using static CodeLiturgy.Data.Auth.Context.Users.Constants;
namespace CodeLiturgy.Data.Auth.Context.Users;
public class JwtFactory : IJwtFactory
{
private readonly IJwtTokenHandler _jwtTokenHandler;
private readonly JwtIssuerOptions _jwtOptions;
public JwtFactory(IJwtTokenHandler jwtTokenHandler, IOptions<JwtIssuerOptions> jwtOptions)
{
_jwtTokenHandler = jwtTokenHandler;
_jwtOptions = jwtOptions.Value;
ThrowIfInvalidOptions(_jwtOptions);
}
public async Task<AccessToken> GenerateEncodedToken(string id, string userName)
{
var identity = GenerateClaimsIdentity(id, userName);
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, userName),
new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()),
new Claim(JwtRegisteredClaimNames.Aud, _jwtOptions.Audience),
new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(),
ClaimValueTypes.Integer64),
identity.FindFirst(JwtClaimIdentifiers.Rol),
identity.FindFirst(JwtClaimIdentifiers.Id)
};
// Create the JWT security token and encode it.
var jwt = new JwtSecurityToken(
_jwtOptions.Issuer,
_jwtOptions.Audience,
claims,
_jwtOptions.NotBefore,
_jwtOptions.Expiration,
_jwtOptions.SigningCredentials);
return new AccessToken(_jwtTokenHandler.WriteToken(jwt), (int)_jwtOptions.ValidFor.TotalSeconds);
}
private static ClaimsIdentity GenerateClaimsIdentity(string id, string userName)
{
return new ClaimsIdentity(new GenericIdentity(userName, "Token"), new[]
{
new Claim(JwtClaimIdentifiers.Id, id),
new Claim(JwtClaimIdentifiers.Rol, JwtClaims.ApiAccess)
});
}
/// <returns>Date converted to seconds since Unix epoch (Jan 1, 1970, midnight UTC).</returns>
private static long ToUnixEpochDate(DateTime date)
=> (long)Math.Round((date.ToUniversalTime() -
new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero))
.TotalSeconds);
private static void ThrowIfInvalidOptions(JwtIssuerOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
if (options.ValidFor <= TimeSpan.Zero)
{
throw new ArgumentException("Must be a non-zero TimeSpan.", nameof(JwtIssuerOptions.ValidFor));
}
if (options.SigningCredentials == null)
{
throw new ArgumentNullException(nameof(JwtIssuerOptions.SigningCredentials));
}
if (options.JtiGenerator == null)
{
throw new ArgumentNullException(nameof(JwtIssuerOptions.JtiGenerator));
}
}
}

View File

@ -1,54 +0,0 @@
using System;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Tokens;
namespace CodeLiturgy.Data.Auth.Context.Users;
public class JwtIssuerOptions
{
/// <summary>
/// 4.1.1. "iss" (Issuer) Claim - The "iss" (issuer) claim identifies the principal that issued the JWT.
/// </summary>
public string Issuer { get; set; }
/// <summary>
/// 4.1.2. "sub" (Subject) Claim - The "sub" (subject) claim identifies the principal that is the subject of the JWT.
/// </summary>
public string Subject { get; set; }
/// <summary>
/// 4.1.3. "aud" (Audience) Claim - The "aud" (audience) claim identifies the recipients that the JWT is intended for.
/// </summary>
public string Audience { get; set; }
/// <summary>
/// 4.1.4. "exp" (Expiration Time) Claim - The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing.
/// </summary>
public DateTime Expiration => IssuedAt.Add(ValidFor);
/// <summary>
/// 4.1.5. "nbf" (Not Before) Claim - The "nbf" (not before) claim identifies the time before which the JWT MUST NOT be accepted for processing.
/// </summary>
public DateTime NotBefore => DateTime.UtcNow;
/// <summary>
/// 4.1.6. "iat" (Issued At) Claim - The "iat" (issued at) claim identifies the time at which the JWT was issued.
/// </summary>
public DateTime IssuedAt => DateTime.UtcNow;
/// <summary>
/// Set the timespan the token will be valid for (default is 120 min)
/// </summary>
public TimeSpan ValidFor { get; set; } = SessionConstants.DefaultSessionMaxAge;
/// <summary>
/// "jti" (JWT ID) Claim (default ID is a GUID)
/// </summary>
public Func<Task<string>> JtiGenerator =>
() => Task.FromResult(Guid.NewGuid().ToString());
/// <summary>
/// The signing key to use when generating tokens.
/// </summary>
public SigningCredentials SigningCredentials { get; set; }
}

View File

@ -1,53 +0,0 @@
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
namespace CodeLiturgy.Data.Auth.Context.Users;
public class JwtTokenHandler : IJwtTokenHandler
{
private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler;
/// <summary>
/// JwtTokenHandler
/// </summary>
public JwtTokenHandler()
{
_jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
}
/// <summary>
/// Write token
/// </summary>
/// <param name="jwt"></param>
/// <returns></returns>
public string WriteToken(JwtSecurityToken jwt)
{
return _jwtSecurityTokenHandler.WriteToken(jwt);
}
/// <summary>
/// Validate Token
/// </summary>
/// <param name="token"></param>
/// <param name="tokenValidationParameters"></param>
/// <returns></returns>
/// <exception cref="SecurityTokenException"></exception>
public ClaimsPrincipal ValidateToken(string token, TokenValidationParameters tokenValidationParameters)
{
try
{
var principal = _jwtSecurityTokenHandler.ValidateToken(token, tokenValidationParameters, out var securityToken);
if (!(securityToken is JwtSecurityToken jwtSecurityToken) || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
throw new SecurityTokenException("Invalid token");
return principal;
}
catch (Exception e)
{
return null;
}
}
}

View File

@ -11,17 +11,18 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNet.Mvc" Version="5.2.9" /> <PackageReference Include="Microsoft.AspNet.Mvc" Version="5.2.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.0" />
<PackageReference Include="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="7.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="7.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authorization.Policy" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.0"> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.0">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="7.0.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CodeLiturgy.Data.Auth\CodeLiturgy.Data.Auth.csproj" />
<ProjectReference Include="..\CodeLiturgy.Domain\CodeLiturgy.Domain.csproj" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-grid.css" /> <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-grid.css" />
<_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-grid.css.map" /> <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-grid.css.map" />
@ -112,7 +113,6 @@
<Folder Include="wwwroot\static\profile" /> <Folder Include="wwwroot\static\profile" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\CodeLiturgy.Data.Application\CodeLiturgy.Data.Application.csproj" />
<ProjectReference Include="..\include\BlueWest.EfMethods\src\BlueWest.EfMethods\BlueWest.EfMethods.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> <ProjectReference Include="..\include\BlueWest.EfMethods\src\BlueWest.EfMethods\BlueWest.EfMethods.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup> </ItemGroup>
@ -134,6 +134,14 @@
<ProjectReference Include="..\include\BlueWest.MapTo\src\BlueWest.MapTo\BlueWest.MapTo.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> <ProjectReference Include="..\include\BlueWest.MapTo\src\BlueWest.MapTo\BlueWest.MapTo.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\include\Math-Expression-Evaluator\SimpleExpressionEvaluator\SimpleExpressionEvaluator.csproj" /> <ProjectReference Include="..\include\Math-Expression-Evaluator\SimpleExpressionEvaluator\SimpleExpressionEvaluator.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Reference Include="Duende.IdentityServer">
<HintPath>..\..\..\..\..\.nuget\packages\duende.identityserver\6.0.4\lib\net6.0\Duende.IdentityServer.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore">
<HintPath>..\..\..\..\..\.nuget\packages\microsoft.aspnetcore.identity.entityframeworkcore\7.0.0\lib\net7.0\Microsoft.AspNetCore.Identity.EntityFrameworkCore.dll</HintPath>
</Reference>
</ItemGroup>
<Import Project="..\include\BlueWest.MapTo\src\BlueWest.MapTo\MapTo.props" /> <Import Project="..\include\BlueWest.MapTo\src\BlueWest.MapTo\MapTo.props" />
</Project> </Project>

View File

@ -3,9 +3,6 @@ using Microsoft.AspNetCore.Mvc;
using CodeLiturgy.Views.Utils; using CodeLiturgy.Views.Utils;
using Duende.IdentityServer.Extensions; using Duende.IdentityServer.Extensions;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using Controller = Microsoft.AspNetCore.Mvc.Controller;
namespace CodeLiturgy.Views.Controllers; namespace CodeLiturgy.Views.Controllers;
[System.Web.Mvc.Route("/")] [System.Web.Mvc.Route("/")]

View File

@ -0,0 +1,401 @@
// <auto-generated />
using System;
using CodeLiturgy.Domain;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace CodeLiturgy.Views.Migrations
{
[DbContext(typeof(ApplicationUserDbContext))]
[Migration("20221118003233_first")]
partial class first
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("CodeLiturgy.Data.Application.Site", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("text");
b.Property<DateTime>("CreatedDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("Domain")
.HasColumnType("text");
b.Property<string>("EnvironmentId")
.HasColumnType("text");
b.Property<int>("EnvironmentType")
.HasColumnType("integer");
b.Property<DateTime>("LastChanged")
.HasColumnType("timestamp with time zone");
b.Property<string>("UrlAddress")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("EnvironmentId");
b.ToTable("Site");
});
modelBuilder.Entity("CodeLiturgy.Data.Application.SiteEnvironment", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("UserId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("site_env", (string)null);
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationRole", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationRoleClaim", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ApplicationRoleId")
.HasColumnType("text");
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ApplicationRoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUser", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("AccessFailedCount")
.HasColumnType("integer");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean");
b.Property<bool>("LockoutEnabled")
.HasColumnType("boolean");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("PasswordHash")
.HasColumnType("text");
b.Property<string>("PhoneNumber")
.HasColumnType("text");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("boolean");
b.Property<string>("SecurityStamp")
.HasColumnType("text");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("boolean");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUserClaim", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ApplicationUserId")
.HasColumnType("text");
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ApplicationUserId");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUserLogin", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("ProviderKey")
.HasColumnType("text");
b.Property<string>("ProviderDisplayName")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUserRole", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("RoleId")
.HasColumnType("text");
b.Property<string>("ApplicationRoleId")
.HasColumnType("text");
b.Property<string>("UserId1")
.HasColumnType("text");
b.HasKey("UserId", "RoleId");
b.HasIndex("ApplicationRoleId");
b.HasIndex("RoleId");
b.HasIndex("UserId1");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUserToken", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Value")
.HasColumnType("text");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Site", b =>
{
b.HasOne("CodeLiturgy.Data.Application.SiteEnvironment", "Environment")
.WithMany("Sites")
.HasForeignKey("EnvironmentId");
b.Navigation("Environment");
});
modelBuilder.Entity("CodeLiturgy.Data.Application.SiteEnvironment", b =>
{
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationUser", "User")
.WithMany("Environments")
.HasForeignKey("UserId");
b.Navigation("User");
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationRoleClaim", b =>
{
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationRole", "ApplicationRole")
.WithMany()
.HasForeignKey("ApplicationRoleId");
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ApplicationRole");
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUserClaim", b =>
{
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationUser", "ApplicationUser")
.WithMany()
.HasForeignKey("ApplicationUserId");
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ApplicationUser");
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUserLogin", b =>
{
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUserRole", b =>
{
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationRole", "ApplicationRole")
.WithMany()
.HasForeignKey("ApplicationRoleId");
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationUser", "User")
.WithMany()
.HasForeignKey("UserId1");
b.Navigation("ApplicationRole");
b.Navigation("User");
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUserToken", b =>
{
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("CodeLiturgy.Data.Application.SiteEnvironment", b =>
{
b.Navigation("Sites");
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUser", b =>
{
b.Navigation("Environments");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,324 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace CodeLiturgy.Views.Migrations
{
/// <inheritdoc />
public partial class first : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetUsers",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
UserName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
Email = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(type: "boolean", nullable: false),
PasswordHash = table.Column<string>(type: "text", nullable: true),
SecurityStamp = table.Column<string>(type: "text", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "text", nullable: true),
PhoneNumber = table.Column<string>(type: "text", nullable: true),
PhoneNumberConfirmed = table.Column<bool>(type: "boolean", nullable: false),
TwoFactorEnabled = table.Column<bool>(type: "boolean", nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
LockoutEnabled = table.Column<bool>(type: "boolean", nullable: false),
AccessFailedCount = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetRoleClaims",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
RoleId = table.Column<string>(type: "text", nullable: false),
ApplicationRoleId = table.Column<string>(type: "text", nullable: true),
ClaimType = table.Column<string>(type: "text", nullable: true),
ClaimValue = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetRoleClaims_AspNetRoles_ApplicationRoleId",
column: x => x.ApplicationRoleId,
principalTable: "AspNetRoles",
principalColumn: "Id");
table.ForeignKey(
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserClaims",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
UserId = table.Column<string>(type: "text", nullable: false),
ApplicationUserId = table.Column<string>(type: "text", nullable: true),
ClaimType = table.Column<string>(type: "text", nullable: true),
ClaimValue = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetUserClaims_AspNetUsers_ApplicationUserId",
column: x => x.ApplicationUserId,
principalTable: "AspNetUsers",
principalColumn: "Id");
table.ForeignKey(
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserLogins",
columns: table => new
{
LoginProvider = table.Column<string>(type: "text", nullable: false),
ProviderKey = table.Column<string>(type: "text", nullable: false),
ProviderDisplayName = table.Column<string>(type: "text", nullable: true),
UserId = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
table.ForeignKey(
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserRoles",
columns: table => new
{
UserId = table.Column<string>(type: "text", nullable: false),
RoleId = table.Column<string>(type: "text", nullable: false),
UserId1 = table.Column<string>(type: "text", nullable: true),
ApplicationRoleId = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_ApplicationRoleId",
column: x => x.ApplicationRoleId,
principalTable: "AspNetRoles",
principalColumn: "Id");
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId1",
column: x => x.UserId1,
principalTable: "AspNetUsers",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "AspNetUserTokens",
columns: table => new
{
UserId = table.Column<string>(type: "text", nullable: false),
LoginProvider = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
Id = table.Column<string>(type: "text", nullable: true),
Value = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
table.ForeignKey(
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "site_env",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "text", nullable: true),
UserId = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_site_env", x => x.Id);
table.ForeignKey(
name: "FK_site_env_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "Site",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
EnvironmentId = table.Column<string>(type: "text", nullable: true),
Domain = table.Column<string>(type: "text", nullable: true),
UrlAddress = table.Column<string>(type: "text", nullable: true),
EnvironmentType = table.Column<int>(type: "integer", nullable: false),
CreatedDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
LastChanged = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Site", x => x.Id);
table.ForeignKey(
name: "FK_Site_site_env_EnvironmentId",
column: x => x.EnvironmentId,
principalTable: "site_env",
principalColumn: "Id");
});
migrationBuilder.CreateIndex(
name: "IX_AspNetRoleClaims_ApplicationRoleId",
table: "AspNetRoleClaims",
column: "ApplicationRoleId");
migrationBuilder.CreateIndex(
name: "IX_AspNetRoleClaims_RoleId",
table: "AspNetRoleClaims",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "RoleNameIndex",
table: "AspNetRoles",
column: "NormalizedName",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_AspNetUserClaims_ApplicationUserId",
table: "AspNetUserClaims",
column: "ApplicationUserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserClaims_UserId",
table: "AspNetUserClaims",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserLogins_UserId",
table: "AspNetUserLogins",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserRoles_ApplicationRoleId",
table: "AspNetUserRoles",
column: "ApplicationRoleId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserRoles_RoleId",
table: "AspNetUserRoles",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserRoles_UserId1",
table: "AspNetUserRoles",
column: "UserId1");
migrationBuilder.CreateIndex(
name: "EmailIndex",
table: "AspNetUsers",
column: "NormalizedEmail");
migrationBuilder.CreateIndex(
name: "UserNameIndex",
table: "AspNetUsers",
column: "NormalizedUserName",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Site_EnvironmentId",
table: "Site",
column: "EnvironmentId");
migrationBuilder.CreateIndex(
name: "IX_site_env_UserId",
table: "site_env",
column: "UserId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AspNetRoleClaims");
migrationBuilder.DropTable(
name: "AspNetUserClaims");
migrationBuilder.DropTable(
name: "AspNetUserLogins");
migrationBuilder.DropTable(
name: "AspNetUserRoles");
migrationBuilder.DropTable(
name: "AspNetUserTokens");
migrationBuilder.DropTable(
name: "Site");
migrationBuilder.DropTable(
name: "AspNetRoles");
migrationBuilder.DropTable(
name: "site_env");
migrationBuilder.DropTable(
name: "AspNetUsers");
}
}
}

View File

@ -0,0 +1,398 @@
// <auto-generated />
using System;
using CodeLiturgy.Domain;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace CodeLiturgy.Views.Migrations
{
[DbContext(typeof(ApplicationUserDbContext))]
partial class ApplicationUserDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("CodeLiturgy.Data.Application.Site", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("text");
b.Property<DateTime>("CreatedDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("Domain")
.HasColumnType("text");
b.Property<string>("EnvironmentId")
.HasColumnType("text");
b.Property<int>("EnvironmentType")
.HasColumnType("integer");
b.Property<DateTime>("LastChanged")
.HasColumnType("timestamp with time zone");
b.Property<string>("UrlAddress")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("EnvironmentId");
b.ToTable("Site");
});
modelBuilder.Entity("CodeLiturgy.Data.Application.SiteEnvironment", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("UserId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("site_env", (string)null);
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationRole", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationRoleClaim", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ApplicationRoleId")
.HasColumnType("text");
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ApplicationRoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUser", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("AccessFailedCount")
.HasColumnType("integer");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean");
b.Property<bool>("LockoutEnabled")
.HasColumnType("boolean");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("PasswordHash")
.HasColumnType("text");
b.Property<string>("PhoneNumber")
.HasColumnType("text");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("boolean");
b.Property<string>("SecurityStamp")
.HasColumnType("text");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("boolean");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUserClaim", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ApplicationUserId")
.HasColumnType("text");
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ApplicationUserId");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUserLogin", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("ProviderKey")
.HasColumnType("text");
b.Property<string>("ProviderDisplayName")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUserRole", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("RoleId")
.HasColumnType("text");
b.Property<string>("ApplicationRoleId")
.HasColumnType("text");
b.Property<string>("UserId1")
.HasColumnType("text");
b.HasKey("UserId", "RoleId");
b.HasIndex("ApplicationRoleId");
b.HasIndex("RoleId");
b.HasIndex("UserId1");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUserToken", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Value")
.HasColumnType("text");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Site", b =>
{
b.HasOne("CodeLiturgy.Data.Application.SiteEnvironment", "Environment")
.WithMany("Sites")
.HasForeignKey("EnvironmentId");
b.Navigation("Environment");
});
modelBuilder.Entity("CodeLiturgy.Data.Application.SiteEnvironment", b =>
{
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationUser", "User")
.WithMany("Environments")
.HasForeignKey("UserId");
b.Navigation("User");
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationRoleClaim", b =>
{
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationRole", "ApplicationRole")
.WithMany()
.HasForeignKey("ApplicationRoleId");
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ApplicationRole");
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUserClaim", b =>
{
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationUser", "ApplicationUser")
.WithMany()
.HasForeignKey("ApplicationUserId");
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ApplicationUser");
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUserLogin", b =>
{
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUserRole", b =>
{
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationRole", "ApplicationRole")
.WithMany()
.HasForeignKey("ApplicationRoleId");
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationUser", "User")
.WithMany()
.HasForeignKey("UserId1");
b.Navigation("ApplicationRole");
b.Navigation("User");
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUserToken", b =>
{
b.HasOne("CodeLiturgy.Data.Application.Users.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("CodeLiturgy.Data.Application.SiteEnvironment", b =>
{
b.Navigation("Sites");
});
modelBuilder.Entity("CodeLiturgy.Data.Application.Users.ApplicationUser", b =>
{
b.Navigation("Environments");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -41,48 +41,6 @@ namespace CodeLiturgy.Domain.Model
/// <param name="modelBuilder"></param> /// <param name="modelBuilder"></param>
private static ModelBuilder ConfigureAppContextModel(this ModelBuilder builder) private static ModelBuilder ConfigureAppContextModel(this ModelBuilder builder)
{ {
builder.Entity<ApplicationUser>(b =>
{
b.HasMany<ApplicationUserRole>()
.WithOne(b => b.User)
.HasForeignKey(ur => ur.UserId).IsRequired();
});
builder.Entity<ApplicationUser>()
.HasKey(x => x.Id);
builder.Entity<ApplicationRole>(b =>
{
b.HasKey(r => r.Id);
b.HasIndex(r => r.NormalizedName).HasDatabaseName("RoleNameIndex").IsUnique();
b.ToTable("roles");
b.Property(r => r.ConcurrencyStamp).IsConcurrencyToken();
b.Property(u => u.Name).HasMaxLength(256);
b.Property(u => u.NormalizedName).HasMaxLength(256);
b.HasMany<ApplicationUserRole>().WithOne().HasForeignKey(ur => ur.RoleId).IsRequired();
b.HasMany<ApplicationRoleClaim>().WithOne().HasForeignKey(rc => rc.RoleId).IsRequired();
});
builder.Entity<ApplicationUserRole>().HasOne(x => x.ApplicationRole);
builder.Entity<ApplicationRoleClaim>().HasOne<ApplicationRole>(x => x.ApplicationRole);
builder.Entity<ApplicationUserClaim>().HasOne<ApplicationUser>(x => x.ApplicationUser);
builder.Entity<ApplicationRoleClaim>(b =>
{
b.HasKey(rc => rc.Id);
});
builder.Entity<ApplicationUserRole>(b =>
{
b.HasKey(r => new {r.UserId, r.RoleId});
});
return builder; return builder;
//.ConfigureIdentityModel(); //.ConfigureIdentityModel();

View File

@ -7,10 +7,8 @@ using CodeLiturgy.Domain;
using BlueWest.WebApi.Context.Users; using BlueWest.WebApi.Context.Users;
using CodeLiturgy.Views.Utils; using CodeLiturgy.Views.Utils;
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
namespace CodeLiturgy.Views; namespace CodeLiturgy.Views;
@ -47,8 +45,6 @@ public static class StartupExtensions
}); });
services services
.AddScoped<IJwtTokenHandler, JwtTokenHandler>()
.AddScoped<IJwtFactory, JwtFactory>()
.AddScoped<UserRepository>() .AddScoped<UserRepository>()
.AddScoped<IUserManager, ApplicationUserManager>() .AddScoped<IUserManager, ApplicationUserManager>()
.AddScoped<IAuthManager, AuthManager>() .AddScoped<IAuthManager, AuthManager>()
@ -60,72 +56,24 @@ public static class StartupExtensions
// Register the ConfigurationBuilder instance of AuthSettings // Register the ConfigurationBuilder instance of AuthSettings
var authSettings = configuration.GetSection(nameof(AuthSettings)); var authSettings = configuration.GetSection(nameof(AuthSettings));
services.Configure<AuthSettings>(authSettings); services.Configure<AuthSettings>(authSettings);
var signingKey = new SymmetricSecurityKey
(Encoding.ASCII.GetBytes(authSettings[nameof(AuthSettings.SecretKey)]));
// jwt wire up
// Get options from app settings
var jwtAppSettingOptions = configuration
.GetSection(nameof(JwtIssuerOptions));
// Configure JwtIssuerOptions
services.Configure<JwtIssuerOptions>(options =>
{
options.Issuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
options.Audience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)];
options.SigningCredentials = new SigningCredentials
(signingKey, SecurityAlgorithms.HmacSha256);
});
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],
ValidateAudience = true,
ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey,
RequireExpirationTime = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
services.AddAuthentication(options => services.AddAuthentication(options =>
{ {
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}) })
.AddCookie(options => .AddCookie(options =>
{ {
options.LoginPath = Routes.AuthLoginRoute; options.LoginPath = Routes.AuthLoginRoute;
options.LogoutPath = Routes.AuthLogoutRoute; options.LogoutPath = Routes.AuthLogoutRoute;
})
.AddJwtBearer(configureOptions =>
{
configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
configureOptions.TokenValidationParameters = tokenValidationParameters;
configureOptions.SaveToken = true;
configureOptions.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
}
return Task.CompletedTask;
},
};
}); });
// api user claim policy // api user claim policy
services.AddAuthorization(options => services.AddAuthorization(options =>
{ {

View File

@ -1,6 +1,6 @@
@using CodeLiturgy.Views.Utils @using CodeLiturgy.Views.Utils
@using Duende.IdentityServer.Extensions
@using CodeLiturgy.Data.Auth @using CodeLiturgy.Data.Auth
@using Duende.IdentityServer.Extensions
@{ @{
Layout = null; Layout = null;
var userAuthenticated = User.IsAuthenticated(); var userAuthenticated = User.IsAuthenticated();