Commit 66244a3a authored by Michael Herndon's avatar Michael Herndon

WORK: integration EFCore, add agent app

parent 6e49817d
......@@ -32,6 +32,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NerdyMishka.Extensions.Proto.Flex.Tests", "test\Extensions\Proto.Flex\NerdyMishka.Extensions.Proto.Flex.Tests.csproj", "{6DC5653A-F974-4A10-AAC4-8AA5AC3C6293}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EfCore", "EfCore", "{B9AAC611-6D86-4B36-AA11-0848B026EEB0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NerdyMishka.EfCore.Relational", "src\EfCore\Relational\NerdyMishka.EfCore.Relational.csproj", "{5C63A82C-1806-4C6D-970C-F630E643B007}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NerdyMishka.EfCore.Identity.Models", "src\EfCore\Identity.Models\NerdyMishka.EfCore.Identity.Models.csproj", "{54531870-3B27-45A6-A27B-5A10BDA6EE89}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NerdyMishka.Extensions.Identity.EfCore", "src\Extensions\Identity.EfCore\NerdyMishka.Extensions.Identity.EfCore.csproj", "{85DF8D0D-09CC-4C22-94AF-FFBBC6ED37D1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Apps", "Apps", "{07B4A7C1-57E6-48D2-810D-BB8F234EECFF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NerdyMishka.Agent", "src\Apps\Agent\NerdyMishka.Agent.csproj", "{9A92EBB7-F59F-46A3-A956-FA00C4093EEC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -66,6 +78,22 @@ Global
{6DC5653A-F974-4A10-AAC4-8AA5AC3C6293}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6DC5653A-F974-4A10-AAC4-8AA5AC3C6293}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6DC5653A-F974-4A10-AAC4-8AA5AC3C6293}.Release|Any CPU.Build.0 = Release|Any CPU
{5C63A82C-1806-4C6D-970C-F630E643B007}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5C63A82C-1806-4C6D-970C-F630E643B007}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5C63A82C-1806-4C6D-970C-F630E643B007}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5C63A82C-1806-4C6D-970C-F630E643B007}.Release|Any CPU.Build.0 = Release|Any CPU
{54531870-3B27-45A6-A27B-5A10BDA6EE89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{54531870-3B27-45A6-A27B-5A10BDA6EE89}.Debug|Any CPU.Build.0 = Debug|Any CPU
{54531870-3B27-45A6-A27B-5A10BDA6EE89}.Release|Any CPU.ActiveCfg = Release|Any CPU
{54531870-3B27-45A6-A27B-5A10BDA6EE89}.Release|Any CPU.Build.0 = Release|Any CPU
{85DF8D0D-09CC-4C22-94AF-FFBBC6ED37D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{85DF8D0D-09CC-4C22-94AF-FFBBC6ED37D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85DF8D0D-09CC-4C22-94AF-FFBBC6ED37D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{85DF8D0D-09CC-4C22-94AF-FFBBC6ED37D1}.Release|Any CPU.Build.0 = Release|Any CPU
{9A92EBB7-F59F-46A3-A956-FA00C4093EEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9A92EBB7-F59F-46A3-A956-FA00C4093EEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9A92EBB7-F59F-46A3-A956-FA00C4093EEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9A92EBB7-F59F-46A3-A956-FA00C4093EEC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......@@ -84,6 +112,12 @@ Global
{AE8D86C2-451F-4505-AC56-1703F0BFB123} = {7705CFA1-C4EB-4D6B-A9EE-4F782C589FD7}
{8CEB02B9-A9A9-4660-A023-41E357B52DFA} = {DA32C16D-7292-4EEC-90C5-59EC66CC018D}
{6DC5653A-F974-4A10-AAC4-8AA5AC3C6293} = {8CEB02B9-A9A9-4660-A023-41E357B52DFA}
{B9AAC611-6D86-4B36-AA11-0848B026EEB0} = {DB042499-08A3-4C34-9231-1372043915F2}
{5C63A82C-1806-4C6D-970C-F630E643B007} = {B9AAC611-6D86-4B36-AA11-0848B026EEB0}
{54531870-3B27-45A6-A27B-5A10BDA6EE89} = {B9AAC611-6D86-4B36-AA11-0848B026EEB0}
{85DF8D0D-09CC-4C22-94AF-FFBBC6ED37D1} = {6444BF0F-2EED-404A-AC00-CC756F4F4ED0}
{07B4A7C1-57E6-48D2-810D-BB8F234EECFF} = {DB042499-08A3-4C34-9231-1372043915F2}
{9A92EBB7-F59F-46A3-A956-FA00C4093EEC} = {07B4A7C1-57E6-48D2-810D-BB8F234EECFF}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {16666A01-3CC0-4111-8A58-9A6CA34CD76C}
......
......@@ -235,7 +235,7 @@ namespace NerdyMishka.Management.Automation
public override void Write(ConsoleColor foregroundColor, ConsoleColor backgroundColor, string value)
{
var fcolor = this.console.ForegroundColor;
var fgColor = this.console.ForegroundColor;
var bgColor = this.console.BackgroundColor;
this.console.ForegroundColor = foregroundColor;
this.console.BackgroundColor = backgroundColor;
......@@ -243,7 +243,7 @@ namespace NerdyMishka.Management.Automation
this.console.Write(value);
this.logger?.LogInformation(value);
this.console.ForegroundColor = fcolor;
this.console.ForegroundColor = fgColor;
this.console.BackgroundColor = bgColor;
}
......
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UserSecretsId>dotnet-NerdyMishka.Agent-1F53F59E-385F-4CCD-B73C-9E1126BFCAA9</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.0" />
<PackageReference Include="Serilog" Version="2.9.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.RollingFile" Version="3.3.0" />
<PackageReference Include="Microsoft.Graph" Version="1.21.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.0" />
<PackageReference Include="Microsoft.Graph.Auth" Version="1.0.0-preview.2" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.7.1" />
<PackageReference Include="Microsoft.Azure.Management.Fluent" Version="1.29.1" />
<PackageReference Include="CommandLineParser" Version="2.7.82" />
<PackageReference Include="ConsoleTables" Version="2.4.0" />
<PackageReference Include="System.Composition" Version="1.4.0" />
<PackageReference Include="Twilio" Version="5.37.1" />
<PackageReference Include="Sendgrid" Version="9.12.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Bcl\Proto\NerdyMishka.Proto.csproj" />
</ItemGroup>
</Project>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace NerdyMishka.Agent
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});
}
}
{
"profiles": {
"NerdyMishka.Agent": {
"commandName": "Project",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace NerdyMishka.Agent
{
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
public Worker(ILogger<Worker> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.Delay(1000, stoppingToken);
}
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
......@@ -203,16 +203,24 @@ namespace NerdyMishka.ComponentModel.ValueConversion
public abstract class ValueEncryptionConverter : ValueConverter
{
/// <summary>
/// Gets or sets the encryption provider for children of the <see cref="ValueEncryptionConverter" />
/// </summary>
/// <value></value>
public static ISymmetricEncryptionProvider EncryptionProvider { get; set; }
private ISymmetricEncryptionProvider encryptionProvider;
public void SetEncryptionProvider(ISymmetricEncryptionProvider provider)
{
this.encryptionProvider = provider;
}
}
public class ValueEncryptionConverter<TFrom, TTo> : ValueEncryptionConverter
{
/// <summary>
/// Gets or sets the encryption provider for the
/// </summary>
/// <value></value>
public static ISymmetricEncryptionProvider EncryptionProvider { get; set; }
private ISymmetricEncryptionProvider encryptionProvider;
......
......@@ -137,9 +137,9 @@ namespace NerdyMishka.Reflection.Extensions
var query = typeof(IList<>);
var result = false;
foreach(var iinterface in type.Interfaces)
foreach(var contract in type.Interfaces)
{
var clrType = iinterface.ClrType;
var clrType = contract.ClrType;
if(clrType.IsGenericType && !clrType.IsGenericTypeDefinition)
{
clrType = clrType.GetGenericTypeDefinition();
......@@ -171,9 +171,9 @@ namespace NerdyMishka.Reflection.Extensions
var query = typeof(IDictionary<,>);
var result = false;
foreach(var iinterface in type.Interfaces)
foreach(var contract in type.Interfaces)
{
var clrType = iinterface.ClrType;
var clrType = contract.ClrType;
if(clrType.IsGenericType && !clrType.IsGenericTypeDefinition)
{
clrType = clrType.GetGenericTypeDefinition();
......@@ -205,9 +205,9 @@ namespace NerdyMishka.Reflection.Extensions
var query = typeof(ICollection<>);
var result = false;
foreach(var iinterface in type.Interfaces)
foreach(var contract in type.Interfaces)
{
var clrType = iinterface.ClrType;
var clrType = contract.ClrType;
if(clrType.IsGenericType && !clrType.IsGenericTypeDefinition)
{
clrType = clrType.GetGenericTypeDefinition();
......
......@@ -20,6 +20,7 @@ namespace NerdyMishka.Reflection
this.PropertyInfo = info;
this.CanWrite = info.CanWrite;
this.CanRead = info.CanRead;
if(info.GetMethod != null)
{
this.IsStatic = info.GetMethod.IsStatic;
......
......@@ -6,7 +6,7 @@ using System.Text;
namespace NerdyMishka.Security.Cryptography
{
/// <summary>
/// Hash-Based Message Authenticated Code Stream that adds authenicated codes
/// Hash-Based Message Authenticated Code Stream that adds authenticated codes
/// using a given hash
/// </summary>
public class HMACBlockStream : System.IO.Stream
......
namespace NerdyMishka.Security.Cryptography
{
public interface IHashProvider
{
byte[] ComputeHash(byte[] value);
}
}
\ No newline at end of file
namespace NerdyMishka.Security.Cryptography
{
public interface IPasswordAuthenticator
public interface IPasswordAuthenticator : IHashProvider
{
byte[] ComputeHash(byte[] value);
bool Verify(byte[] value, byte[] hash);
}
}
\ No newline at end of file
......@@ -2,14 +2,22 @@ using System;
namespace NerdyMishka.Security.Cryptography
{
public interface ISymmetricEncryptionProvider : IDisposable
{
byte[] Encrypt(byte[] data);
byte[] Encrypt(
byte[] data,
byte[] privateKey = null,
byte[] symmetricKey = null,
IEncryptionProvider symmetricKeyEncryptionProvider = null);
byte[] Decrypt(byte[] data);
byte[] Decrypt(
byte[] data,
byte[] privateKey = null,
......
......@@ -15,6 +15,8 @@ namespace NerdyMishka.Security.Cryptography
/// <summary>
/// Generates a unique id that is compatible with key pass.
......
using System;
using System.Collections.Generic;
using System.Linq;
using NerdyMishka.Flex;
using NerdyMishka.ComponentModel.DataAnnotations;
namespace NerdyMishka.EfCore.Identity
{
......@@ -22,13 +22,10 @@ namespace NerdyMishka.EfCore.Identity
public string Name { get; set; }
public string Code { get; set; }
[Hash]
public string Value { get; set; }
public DateTime? ExpiresAt { get; set; }
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using NerdyMishka.Flex;
namespace NerdyMishka.EfCore.Identity
{
......@@ -11,7 +10,6 @@ namespace NerdyMishka.EfCore.Identity
public virtual ApiKey ApiKey { get; set; }
public virtual int RoleId { get; set; }
public virtual Role Role { get; set; }
......
using System;
using NerdyMishka.Flex;
using NerdyMishka.ComponentModel.DataAnnotations;
namespace NerdyMishka.EfCore.Identity
{
......@@ -11,7 +11,7 @@ namespace NerdyMishka.EfCore.Identity
public virtual User User { get; set; }
public Guid SyncKey { get; set; } = Guid.NewGuid();
public Guid SyncKey { get; set; } = Guid.NewGuid();
public string Name { get; set;}
......
......@@ -62,23 +62,22 @@ namespace NerdyMishka.EfCore.Identity
{
builder.HasKey(o => o.Id);
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
builder.Property(o => o.Pseudonym)
.HasMaxLength(35);
builder.Property(o => o.Email)
.HasMaxLength(1024);
}
public virtual void Configure(EntityTypeBuilder<PasswordLogin> builder)
{
builder.HasKey(o => o.UserId);
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
builder.Property(o => o.UserId)
.ValueGeneratedNever();
......@@ -89,7 +88,8 @@ namespace NerdyMishka.EfCore.Identity
public void Configure(EntityTypeBuilder<ApiKey> builder)
{
builder.HasKey(o => o.Id);
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
builder.Property(o => o.Name)
.HasMaxLength(100)
.IsRequired();
......@@ -97,9 +97,6 @@ namespace NerdyMishka.EfCore.Identity
builder.Property(o => o.Value)
.HasMaxLength(1024)
.IsRequired();
}
public class EmailPurposeConverter : EnumToNumberConverter<EmailPurpose, int>
......@@ -115,7 +112,9 @@ namespace NerdyMishka.EfCore.Identity
public void Configure(EntityTypeBuilder<EmailAddress> builder)
{
builder.HasKey(o => o.Id);
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
builder.Property(o => o.Value)
.IsRequired()
.HasMaxLength(512);
......@@ -132,7 +131,8 @@ namespace NerdyMishka.EfCore.Identity
public void Configure(EntityTypeBuilder<Phone> builder)
{
builder.HasKey(o => o.Id);
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
builder.Property(o => o.Value)
.IsRequired()
.HasMaxLength(512);
......@@ -149,13 +149,15 @@ namespace NerdyMishka.EfCore.Identity
public void Configure(EntityTypeBuilder<Domain> builder)
{
builder.HasKey(o => o.Id);
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
}
public void Configure(EntityTypeBuilder<Organization> builder)
{
builder.HasKey(o => o.Id);
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
builder.Property(o => o.Name)
.IsRequired()
......@@ -164,13 +166,13 @@ namespace NerdyMishka.EfCore.Identity
builder.Property(o => o.Code)
.IsRequired()
.HasMaxLength(100);
}
public void Configure(EntityTypeBuilder<MultiFactorPolicy> builder)
{
builder.HasKey(o => o.Id);
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
builder.Property(o => o.Name)
.HasMaxLength(100)
......@@ -193,7 +195,8 @@ namespace NerdyMishka.EfCore.Identity
public void Configure(EntityTypeBuilder<PasswordPolicy> builder)
{
builder.HasKey(o => o.Id);
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
builder.Property(o => o.Name)
.HasMaxLength(100);
......@@ -214,7 +217,9 @@ namespace NerdyMishka.EfCore.Identity
public void Configure(EntityTypeBuilder<Role> builder)
{
builder.HasKey(o => o.Id);
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
builder.Property(o => o.Name)
.IsRequired()
.HasMaxLength(100);
......@@ -240,7 +245,9 @@ namespace NerdyMishka.EfCore.Identity
public void Configure(EntityTypeBuilder<Permission> builder)
{
builder.HasKey(o => o.Id);
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
builder.Property(o => o.Name)
.IsRequired()
.HasMaxLength(100);
......@@ -251,31 +258,34 @@ namespace NerdyMishka.EfCore.Identity
builder.Property(o => o.Description)
.HasMaxLength(256);
}
public virtual void Configure(EntityTypeBuilder<RolePermission> builder)
{
builder.HasKey("RoleId", "PermissionId");
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
}
public virtual void Configure(EntityTypeBuilder<UserRole> builder)
{
builder.HasKey("UserId", "RoleId");
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
}
public virtual void Configure(EntityTypeBuilder<ApiKeyRole> builder)
{
builder.HasKey("ApiKeyId", "RoleId");
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
}
public virtual void Configure(EntityTypeBuilder<UserLogin> builder)
{
builder.HasKey(o => new { o.ProviderName, o.Key });;
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
builder.Property(o => o.UserId)
.ValueGeneratedNever();
......@@ -293,21 +303,21 @@ namespace NerdyMishka.EfCore.Identity
public void Configure(EntityTypeBuilder<UserClaim> builder)
{
builder.HasKey(o => o.Id);
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
builder.Property(o => o.Type)
.IsRequired(true)
.HasMaxLength(512);
builder.Property(o => o.Value);
}
public void Configure(EntityTypeBuilder<RoleClaim> builder)
{
builder.HasKey(o => o.Id);
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
builder.Property(o => o.Type)
.IsRequired(true)
......@@ -319,9 +329,9 @@ namespace NerdyMishka.EfCore.Identity
public void Configure(EntityTypeBuilder<UserToken> builder)
{
builder.HasKey(o => new { o.UserId, o.ProviderName, o.Name });
builder.Metadata.Relational().Schema = this.schemaName;
if(!string.IsNullOrEmpty(this.schemaName))
builder.Metadata.SetSchema(this.schemaName);
}
}
}
\ No newline at end of file
......@@ -5,13 +5,12 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.2.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../EfCore.Relational/NerdyMishka.EfCore.Relational.csproj" />
<ProjectReference Include="../Flex/NerdyMishka.Flex.csproj" />
<ProjectReference Include="../Relational/*.csproj" />
<ProjectReference Include="../../Bcl/Proto/*.csproj" />
</ItemGroup>
</Project>
......@@ -20,17 +20,15 @@ namespace NerdyMishka.EfCore.Identity
public string Name { get; set; }
public int? MultiFactorPolicyId { get; set; }
public int? PasswordPolicyId { get; set; }
public virtual MultiFactorPolicy MultiFactorPolicy { get; set; }
public virtual PasswordPolicy PasswordPolicy { get; set; }
public int? PasswordPolicyId { get; set; }
public virtual ICollection<Domain> Domains { get; set; }
public virtual ICollection<User> Users { get; set;}
}
}
\ No newline at end of file
using System;
using NerdyMishka.Flex;
using NerdyMishka.ComponentModel.DataAnnotations;
namespace NerdyMishka.EfCore.Identity
{
......@@ -34,6 +34,7 @@ namespace NerdyMishka.EfCore.Identity
/// </para>
/// </remarks>
/// <value></value>
[Hash]
public string Password { get; set; }
public DateTime? PasswordUpdatedAt { get; set; }
......@@ -109,21 +110,21 @@ namespace NerdyMishka.EfCore.Identity
/// <summary>
/// Is the password locked from too many attempts?
/// </summary>
/// <param name="isAuthenicated">Was the password authenticated?</param>
/// <param name="isAuthenticated">Was the password authenticated?</param>
/// <param name="span">The timespan for the lockout period.</param>
/// <param name="count">The number of attempts.</param>
/// <returns>True, if the password login is locked; otherwise, false.</returns>
public bool IsLocked(bool isAuthenicated, TimeSpan span, short numberOfAttemptsAllowed = 5)
public bool IsLocked(bool isAuthenticated, TimeSpan span, short numberOfAttemptsAllowed = 5)
{
if(isAuthenicated)
if(isAuthenticated)