public interface Subject extends Contextual
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.
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.
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.getDefaults()
.
Use a SubjectCollection
to create instances.
PermissionService
Modifier and Type | Method and Description |
---|---|
SubjectReference |
asSubjectReference()
Gets a SubjectReference representing this subject.
|
Optional<CommandSource> |
getCommandSource()
Returns a possible
CommandSource for the subject, if it relates
to one. |
SubjectCollection |
getContainingCollection()
Returns the subject collection this subject is a member of.
|
Optional<String> |
getOption(Set<Context> contexts,
String key)
Gets the value of a given option in the given context.
|
default Optional<String> |
getOption(String key)
Gets the value of a given option in the subject's current context.
|
default List<SubjectReference> |
getParents()
Return all parents that this group has in its current context
combination.
|
List<SubjectReference> |
getParents(Set<Context> contexts)
Return all parents that this group has in the given context combination.
|
Tristate |
getPermissionValue(Set<Context> contexts,
String permission)
Returns the calculated value set for a given permission.
|
SubjectData |
getSubjectData()
Returns the primary data backing for this Subject.
|
SubjectData |
getTransientSubjectData()
Returns the transient data backing for this Subject.
|
default boolean |
hasPermission(Set<Context> contexts,
String permission)
Test whether the subject is permitted to perform an action corresponding
to the given permission string.
|
default boolean |
hasPermission(String permission)
Test whether the subject is permitted to perform an action given as the
given permission string.
|
boolean |
isChildOf(Set<Context> contexts,
SubjectReference parent)
Check if this subject is a child of the given parent in the given context
combination, traversing inheritance.
|
default boolean |
isChildOf(SubjectReference parent)
Check if this subject is a child of the given parent in the subject's
current context, traversing inheritance.
|
boolean |
isSubjectDataPersisted()
Returns if this Subject has persistent, non-transient data.
|
getActiveContexts, getFriendlyIdentifier, getIdentifier
Optional<CommandSource> getCommandSource()
CommandSource
for the subject, if it relates
to one.
If this subject represents an actual user currently connected, this method returns this user. This user may in fact be the same as this subject. Some subjects may never directly map to a command source, while others may temporarily not have an accessible command source.
SubjectCollection getContainingCollection()
SubjectReference asSubjectReference()
boolean isSubjectDataPersisted()
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.
SubjectData getSubjectData()
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 getTransientSubjectData()
.
SubjectData getTransientSubjectData()
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 getSubjectData()
.
default boolean hasPermission(Set<Context> contexts, String permission)
This must return the same boolean equivalent as
getPermissionValue(Set, String)
.
contexts
- The set of contexts that represents the subject's current
environmentpermission
- The permission stringdefault boolean hasPermission(String permission)
This must return the same value as hasPermission(Set, String)
using Contextual.getActiveContexts()
.
permission
- The permission stringTristate getPermissionValue(Set<Context> contexts, String 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.getDefaults()
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.
contexts
- The contexts to check for permissions inpermission
- The permission to checkdefault boolean isChildOf(SubjectReference parent)
This must return the same value as
isChildOf(Set, SubjectReference)
using
Contextual.getActiveContexts()
.
parent
- The parent to check for inheritanceboolean isChildOf(Set<Context> contexts, SubjectReference parent)
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.getDefaults()
should be considered for this
lookup.
contexts
- The context combination to check inparent
- The parent to check for inheritancedefault List<SubjectReference> getParents()
This must include inherited values if the permissions service supports inheritance.
It must also must return the same value as getParents(Set)
using Contextual.getActiveContexts()
.
List<SubjectReference> getParents(Set<Context> contexts)
This must include inherited values if the permissions service supports inheritance.
contexts
- The context combination to check inOptional<String> getOption(Set<Context> contexts, String key)
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.getDefaults()
should be considered
for this lookup.
contexts
- The contexts to get the options fromkey
- The key to get an option by. Case-insensitive.default Optional<String> getOption(String key)
This must return the same value as getOption(Set, String)
using Contextual.getActiveContexts()
.
key
- The key to get an option by. Case-insensitive.