AccessKickPolicy
A policy whose consequence is kicking. What triggers it is the binding.
Behaviour and application are separated on purpose: kicking is one thing, and "when someone is not staff" is another. Bind them at the registration site, where both halves read in a line:
maid:GiveTask(accessPolicyService:RegisterPolicy(
maid:Add(AccessKickPolicy.whenFactIs(serviceBag, "kick-on-non-admin", AccessFactNames.PLAYER_IS_ADMIN, false, {
message = "This place is currently limited to the development team.",
}))
))
maid:GiveTask(accessPolicyService:RegisterPolicy(
maid:Add(AccessKickPolicy.whenFeatureDisallowed(serviceBag, "kick-without-chapter-access", MyFeatures.Chapters))
))
GOTCHA, and the reason this is a class rather than a pattern to copy: a kick never fires on an
unanswered input. "We could not find out whether you are staff" is not "you are not staff", and a
policy that kicked on the difference would empty the server every time a lookup hiccupped. Both
bindings below encode that once -- whenFactIs matches the value exactly, so unresolved never equals
false; whenFeatureDisallowed skips AccessStateUtils.isUnresolved, which an author writing
not isAllowed(state) by hand would silently get wrong.
Types
AccessKickTrigger
Emits true when this player should be kicked. Anything it never emits true for never kicks.
Functions
new
The general form. Prefer AccessKickPolicy.whenFactIs or AccessKickPolicy.whenFeatureDisallowed -- they read better and they get the unresolved rule right without you having to remember it.
whenFactIs
AccessKickPolicy.whenFactIs(policyName: string,factName: string,value: boolean,options: {message: string?,isEnabledByDefault: boolean?}?) → AccessPolicyKicks while a fact reads exactly this value.
AccessKickPolicy.whenFactIs("kick-on-non-admin", "playerIsAdmin", false) reads as what it does:
kick when playerIsAdmin is false. Unresolved is not false, so an unanswered lookup kicks nobody.
whenFeatureDisallowed
AccessKickPolicy.whenFeatureDisallowed(policyName: string,options: {message: string?,isEnabledByDefault: boolean?}?) → AccessPolicyKicks while a feature refuses this player for a real reason.
Skips unresolved, which is the whole trap: an unresolved state is a disallowed state, so the obvious
not isAllowed(state) would kick everyone whose lookup had not landed yet.
kick
Kicks the player, mock or otherwise. A PlayerMock has no native Kick, and a policy that only works
against real players cannot be tested without a real session.