ASP.NET Core Identity has UserManager.SupportsUserLockout(), which for me is true.
Description:
Gets a flag indicating whether the backing user store supports user lock-outs.
Is it ever possible for the user manager NOT to support lockouts?
CodePudding user response:
Is it ever possible for the user manager NOT to support lockouts?
Yes
Under any of these 2 circumstances:
UserManager<TUser>is subclassed and thevirtual bool SupportsUserLockoutproperty is overridden and that implementation returnsfalse.UserManager<TUser>.Store(yourIUserStore<TUser>implementation) does not implement the optionalIUserLockoutStore<TUser>interface.
- If you're using the "stock" in-box ASP.NET Core Identity functionality, without using any custom
IUserStoreimplementation (and without subclassingUserManager<TUser>), then your runtimeIUserStore<TUser>will be some subclass ofabstract class UserStoreBase<...>which does implementIUserLockoutStore<TUser>.- e.g. ASP.NET Core Identity for Entity Framework uses
Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserOnlyStorewhich inherits theIUserLockoutStore<TUser>interface implementation.
- e.g. ASP.NET Core Identity for Entity Framework uses
- Because in C#/.NET, interfaces are strictly additive (one cannot "remove" an interface from a class - you can only reimplement it) it means if you don't want to subclass
UserManager<TUser>then you will cannot use a subclassUserStoreBase<>as the basis for your reimplementation ofIUserStore<>- you'll have to start from scratch, basically.- (Which in my mind, at least, means that ASP.NET Core Identity's default combination of
UserManagerandUserStoreBase<...>is a bad OOP design because it requires implementations to actively go through a lot of effort to correctly not support something, instead of making everything opt-in. - Hey kids, inheritance is bad, mmm'key (okay, not "bad", but at least is so fraught with problems it should be avoided.
- Subclass inheritance is a blunt instrument, especially in C# and Java, where it's impossible to separate a type's "interface"1 from implementation, and can't describe a type's interface in a type algebraic way - so we can't define a
class Derivedthat subclasses a parentclass Base : ISomeInterfacesuch thatclass Derivedno longer implementsISomeInterface(the best we can do is either abuse implicit conversions to a separate type, or "hide" members with[EditorBrowsable]and reimplement the interface explicitly withthrow new NotSupportedException(), which is horrible, but even Microsoft does it in some places in .NET's base libraries, such as inStreamandTextWritersubclasses). - (Also, don't (ab)use inheritance just to have "common members" in different types. I agree that it does suck that C#/.NET still doesn't support mixins, but the drudgery of copy pasting forwarder properties and methods around is less painful in the long-term than dealing with the consequences of inappropriate use of inheritance.
- Subclass inheritance is a blunt instrument, especially in C# and Java, where it's impossible to separate a type's "interface"1 from implementation, and can't describe a type's interface in a type algebraic way - so we can't define a
- (Which in my mind, at least, means that ASP.NET Core Identity's default combination of
1: By "interface" I don't mean interface types; I mean the set of public members of a class or struct, i.e. a type's exposed surface.
(In an earlier edit of my post, I suggested that IConfigureOptions<LockoutOptions> could be used to configure SupportsUserLockout, however I was wrong: as there is no option to outright disable the lockout system, but if you were to subclass both LockoutOptions to add a bool Enabled property and subclass UserManager<TUser> to specify override bool SupportsUserLockout to return LockoutOptions.Enabled (ideally, from an immutable copy, not the original mutable options object) then that would work.
