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 SupportsUserLockout
property 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
IUserStore
implementation (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.UserOnlyStore
which 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
UserManager
andUserStoreBase<...>
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 Derived
that subclasses a parentclass Base : ISomeInterface
such thatclass Derived
no 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 inStream
andTextWriter
subclasses). - (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.