Interface Subject

All Superinterfaces:
Contextual
All Known Subinterfaces:
CommandBlock, CommandBlockMinecart, CommandCause, CommandContext, CommandContext.Builder, RconConnection, ServerPlayer, SubjectProxy, SystemSubject, User

public interface Subject extends Contextual
An object which can hold permission data.

Subjects are objects which hold permission data, in the form of SubjectData. They can also be the source of permission requests.

The most common forms of Subject are "users" and "groups", although these are not the only forms. Anything can hold permission data, and therefore be a subject.

Permission strings

Authorization checks are made using "permission strings."

Permission strings are hierarchical with each level separated by periods (full stops). An example of a valid permission string is example.function. Inheritance is implicit; that is, if a subject has been granted example, then the subject should have also be automatically granted example.function, example.another, example.deeper.nesting, and so on. However, implementations may allow administrators to configure "negation" such that example and all child levels would granted but example.access would denied (for example).

It is the responsibility of the PermissionService implementation to provide this behavior, and resolve the implicit permission node inheritance explained above when a Subject is queried for permissions. Use of a NodeTree is recommended.

Plugins may opt to implement "dynamic" permissions such as example.region.define.<region> where region would depend on the context of the check. Attention should be made towards the handling of periods / full stops in such cases.

Due to the implicit inheritance, it is recommended that commands that allow a user to "apply" an effect to other users use example.function.self as the permission for applying this effect to one's self. This allows administrators to grant example.function.self to permit usage on one's self and grant example.function to grant usage on other users.

Inheritance

All methods are expected to account for data inherited from parent subjects. For a representation of the data that the subject explicitly holds, obtain the SubjectData for the subject.

Additionally, all methods are expected to account for the defaults defined in the SubjectCollection containing this subject, as well as the defaults set globally in PermissionService.defaults().

Contexts

Permission state is calculated using small pieces of information known as contexts. These are derived from a provided Cause using ContextCalculators. Subjects have a default cause for context calculation, which is based on the subject's active state.

The relevant active state for subject context may be different depending on which types of permissions are being checked. Mostly, these will fall into either global game state or the subject's own state. While the default implementation of contextCause() provides the latter, some proxy subjects that act as a projection of a subject into a certain state (such as CommandCause may choose to default to the former. The relevant cause stack should be carefully considered when performing permissions checks.

Use a SubjectCollection to access instances.

See Also:
to manage Subjects.
  • Method Details

    • containingCollection

      SubjectCollection containingCollection()
      Returns the subject collection this subject is a member of.
      Returns:
      The appropriate collection
    • asSubjectReference

      SubjectReference asSubjectReference()
      Gets a SubjectReference representing this subject.
      Returns:
      A subject reference representing this subject
    • associatedObject

      Optional<?> associatedObject()
      Get the game object that may be associated with this subject.

      This could be a player, system subject, or something else. The return value of this method should not be stored.

      Returns:
      a potential game object
    • contextCause

      default Cause contextCause()
      Description copied from interface: Contextual
      Get the cause describing the current state of this subject.

      This is often not based on current game state, but rather the last known state of this subject. If a subject refers to a game object that is not active in the world, the cause may be a global cause.

      Specified by:
      contextCause in interface Contextual
      Returns:
      the active cause
    • isSubjectDataPersisted

      boolean isSubjectDataPersisted()
      Returns if this Subject has persistent, non-transient data.

      If true, this subject should have two distinct stores of SubjectData, and the non-transient form should be saved between sessions.

      If false, this subject will have only one store of SubjectData, which will not be persisted between sessions.

      Returns:
      If this Subject has persistent, non-transient data.
    • subjectData

      SubjectData subjectData()
      Returns the primary data backing for this Subject.

      If this Subject is not persisted, this data will not be saved between sessions.

      For subjects which are not persisted, the same store will be returned by transientSubjectData().

      Returns:
      The primary data backing for this Subject
    • transientSubjectData

      SubjectData transientSubjectData()
      Returns the transient data backing for this Subject.

      Transient data is guaranteed to only last for the duration of the subject's session, and is not persisted.

      For subjects which are not persisted, the same store will be returned by subjectData().

      Returns:
      The transient data backing for this Subject
    • hasPermission

      default boolean hasPermission(String permission)
      Test whether the subject is permitted to perform an action given as the given permission string.

      This must return the same value as hasPermission(String, Cause) called with the phase tracker's current cause.

      Parameters:
      permission - The permission string
      Returns:
      True if permission is granted
    • hasPermission

      default boolean hasPermission(String permission, Cause cause)
      Test whether the subject is permitted to perform an action corresponding to the given permission string.

      This must return the same boolean equivalent as permissionValue(String, Cause).

      Parameters:
      permission - The permission string
      cause - The cause stack to extract context information from
      Returns:
      True if permission is granted
    • hasPermission

      default boolean hasPermission(String permission, Set<Context> contexts)
      Test whether the subject is permitted to perform an action corresponding to the given permission string.

      This must return the same boolean equivalent as permissionValue(String, Cause).

      Parameters:
      permission - The permission string
      contexts - The contexts to calculate permission status in
      Returns:
      True if permission is granted
    • permissionValue

      default Tristate permissionValue(String permission)
      Returns the calculated value set for a given permission.

      It is expected that this method will also account for values inherited from parent subjects, as well as permission nodes inherited implicitly from a more generic level.

      Additionally, the defaults defined the SubjectCollection that holds this subject, as well as defaults defined in PermissionService.defaults() should be considered for this lookup.

      This method is likely to be called frequently, so it is desirable that implementations cache the results to method calls.

      Parameters:
      permission - The permission to check
      Returns:
      The tristate result of the check
    • permissionValue

      Tristate permissionValue(String permission, Cause cause)
      Returns the calculated value set for a given permission.

      It is expected that this method will also account for values inherited from parent subjects, as well as permission nodes inherited implicitly from a more generic level.

      Additionally, the defaults defined the SubjectCollection that holds this subject, as well as defaults defined in PermissionService.defaults() should be considered for this lookup.

      This method is likely to be called frequently, so it is desirable that implementations cache the results to method calls.

      Parameters:
      permission - The permission to check
      cause - The cause to gather context from.
      Returns:
      The tristate result of the check
    • permissionValue

      Tristate permissionValue(String permission, Set<Context> contexts)
      Returns the calculated value set for a given permission.

      It is expected that this method will also account for values inherited from parent subjects, as well as permission nodes inherited implicitly from a more generic level.

      Additionally, the defaults defined the SubjectCollection that holds this subject, as well as defaults defined in PermissionService.defaults() should be considered for this lookup.

      This method is likely to be called frequently, so it is desirable that implementations cache the results to method calls.

      Parameters:
      permission - The permission to check
      contexts - The contexts to query permission value in
      Returns:
      The tristate result of the check
    • isChildOf

      default boolean isChildOf(SubjectReference parent)
      Check if this subject is a child of the given parent in the subject's current context, traversing inheritance.

      This must return the same value as isChildOf(SubjectReference, Cause) called with the phase tracker's current cause.

      Parameters:
      parent - The parent to check for inheritance
      Returns:
      Whether this is a child of the given parent
    • isChildOf

      boolean isChildOf(SubjectReference parent, Cause cause)
      Check if this subject is a child of the given parent in the given context combination, traversing inheritance.

      It is expected that this method will also account for data from distant parents, inherited from direct parent subjects.

      Additionally, the defaults defined the SubjectCollection that holds this subject, as well as defaults defined in PermissionService.defaults() should be considered for this lookup.

      Parameters:
      parent - The parent to check for inheritance
      cause - The cause to gather context from.
      Returns:
      Whether this is a child of the given parent
    • isChildOf

      boolean isChildOf(SubjectReference parent, Set<Context> contexts)
      Check if this subject is a child of the given parent in the given context combination, traversing inheritance.

      It is expected that this method will also account for data from distant parents, inherited from direct parent subjects.

      Additionally, the defaults defined the SubjectCollection that holds this subject, as well as defaults defined in PermissionService.defaults() should be considered for this lookup.

      Parameters:
      parent - The parent to check for inheritance
      contexts - The contexts to query inheritance in
      Returns:
      Whether this is a child of the given parent
    • parents

      default List<? extends SubjectReference> parents()
      Return all parents that this group has in its current context combination.

      This must include inherited values if the permissions service supports inheritance.

      It must also must return the same value as parents(Cause)

      Returns:
      An immutable list of parents
    • parents

      List<? extends SubjectReference> parents(Cause cause)
      Return all parents that this group has in the given context combination.

      This must include inherited values if the permissions service supports inheritance.

      Parameters:
      cause - The cause to gather context from.
      Returns:
      An immutable list of parents
    • parents

      List<? extends SubjectReference> parents(Set<Context> contexts)
      Return all parents that this group has in the given context combination.

      This must include inherited values if the permissions service supports inheritance.

      Parameters:
      contexts - The cause to gather context from.
      Returns:
      An immutable list of parents
    • option

      default Optional<String> option(String key)
      Gets the value of a given option in the subject's current context.

      This must return the same value as option(String, Cause) called with the phase tracker's current cause.

      Parameters:
      key - The key to get an option by. Case-insensitive.
      Returns:
      The value of the option, if any is present
    • option

      Optional<String> option(String key, Cause cause)
      Gets the value of a given option in the given context.

      It is expected that this method will account for options inherited from parent subjects.

      Additionally, the default options defined by the SubjectCollection that holds this subject, as well as defaults defined in PermissionService.defaults() should be considered for this lookup.

      Parameters:
      key - The key to get an option by. Case-insensitive.
      cause - The cause to gather context from.
      Returns:
      The value of the option, if any is present
    • option

      Optional<String> option(String key, Set<Context> contexts)
      Gets the value of a given option in the given context.

      It is expected that this method will account for options inherited from parent subjects.

      Additionally, the default options defined by the SubjectCollection that holds this subject, as well as defaults defined in PermissionService.defaults() should be considered for this lookup.

      Parameters:
      key - The key to get an option by. Case-insensitive.
      contexts - The context set to use when calculating causes
      Returns:
      The value of the option, if any is present