Permissions
Permission
Une permission est une chaîne de caractères hiérarchique, sensible à la casse, qui est utilisé pour déterminer si un sujet peut ou non effectuer une action. La chaîne de caractères est séparée en plusieurs parties, chacune séparée par point. Les permissions devraient être structurées comme ceci.
<PluginID>.<MainGroup>.<Subgroup1>...
Les caractères autorisés sont :
« A » - « Z »
« a » - « z »
« 0 » - « 9 »
« _ »
« - »
« . »
Héritage
Si un utilisateur a la permission myPlugin.commands
, automatiquement cet utilisateur disposera de toutes les sous permissions de celle-ci. Comme, par exemple, myPlugin.commands.teleport
à moins que cette permission ait été explicitement enlevée à l’utilisateur.
Note
Il n’y a pas de permission générique comme myPlugin.commands.*
, utilisez myPlugin.commands
pour cela.
Exemple de Structure
L’exemple ci-dessous montre une possibilité pour structurer vos permissions, mais cette structure n’est absolument pas obligatoire.
myPlugin
Donne accès à toutes les permissions de votre plugin.
myPlugin.commands
Donne accès à toutes les commandes de votre plugin.
myPlugin.commands.teleport.execute
Ne permet à l’utilisateur qu’à exécuter la commande. Sans cette permission l’utilisateur n’est pas capable d’exécuter la commande même s’il dispose des autres permissions teleport. (Avec cette permission seule, l’utilisateur n’est capable que de se téléporter à d’autres utilisateurs dans son monde actuel.)
myPlugin.commands.teleport.all
Ne permet à l’utilisateur qu’à téléporter tous les joueurs d’un coup.
myPlugin.commands.teleport.worlds
Ne permet à l’utilisateur qu’à se téléporter aux différents mondes.
myPlugin.commands.teleport.worlds.mynetherworld
Ne permet à l’utilisateur qu’à se téléporter à mynetherworld.
PermissionDescription
La PermissionDescription est un utilitaire qui permet de donner aux propriétaires de serveur une description sur une permission en particulier. La PermissionDescription
est une fonctionnalité optionnelle qu’un PermissionService peut fournir. La création d’une PermissionDescription
n’a aucun impact sur l’existence de la permission, qui y a accès et quelle est sa valeur par défaut.
La description comprend :
l’id de la permission en question
une description textuelle
un ou plusieurs rôles assignés
le plugin possesseur de cette permission
Si vous avez un élément dynamique comme un World
ou un ItemType
vous pouvez utiliser <TemplateParts>
.
Exemple d’Utilisation
import org.spongepowered.api.service.permission.PermissionDescription;
import org.spongepowered.api.service.permission.PermissionDescription.Builder;
import org.spongepowered.api.service.permission.PermissionService;
import org.spongepowered.api.text.Text;
import java.util.Optional;
Optional<Builder> optBuilder = permissionService.newDescriptionBuilder(myPlugin);
if (optBuilder.isPresent()) {
Builder builder = optBuilder.get();
builder.id("myPlugin.commands.teleport.execute")
.description(Text.of("Allows the user to execute the teleport command."))
.assign(PermissionDescription.ROLE_STAFF, true)
.register();
}
Résultat Simple
myPlugin.commands.teleport.execute
Description: Allows the user to execute the teleport command.
Role: user
Owner: MyPlugin v1.2.3
Résultat avec Template
myPlugin.commands.teleport.worlds.<World>
Description: Allows the user to teleport to the world <World>.
Role: staff
Owner: MyPlugin v1.2.3
Astuce
Vous pouvez ignorer l’écriture des descriptions pour certains groupes de permissions parent tel que myPlugin.commands.teleport.worlds
ou myPlugin.commands
comme leur signification peut être déduite de la structure des permissions et seulement définir les permissions enfants.
Sujet
Un Subject est un détenteur de permissions. Il peut être obtenu depuis le PermissionService
par l’intermédiaire de SubjectCollections. Les CommandSources comme les Players sont des Subject
s par défaut, mais il y a beaucoup d’autres types de Subject
s. Tout ce qui dispose d’une permission est un Sujet même si elle délègue simplement les contrôles à un Sujet contenu. Les permissions peuvent être accordées ou refusées à un Sujet. Si une permission n’est ni accordée ni refusée, ses paramètres seront hérités, voir la section sur l’héritage. Les Sujets donnent accès à des méthodes pour vérifier s’ils ont une certaine permission ou non. Les plugins qui utilisent cette méthode doivent uniquement demander les permissions spécifiques qu’ils veulent vérifier. C’est la tâche du PermissionService de respecter la permission et l’héritage de l’objet.
Exemple
L’exemple ci-dessous peut être utilisé pour vérifier si le Joueur est autorisé à exécuter la commande de téléportation.
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.world.World;
public boolean canTeleport(Player subject, World targetWorld) {
return subject.hasPermission("myPlugin.command.teleport.execute")
&& (subject.getWorld() == targetWorld
|| subject.hasPermission("myPlugin.command.teleport." + targetWorld.getName()));
}
Héritage
Si un Subject
possède une permission assignée, il utilisera cette valeur. Dans le cas contraire, la valeur sera héritée de n’importe quel Subject
parent. Peu importe quel genre de Subject
parent (comme un groupe ou un joueur.) il pourrait avoir.
Si ni le sujet lui-même, ni n’importe quel sujet parent n’accorde ou ne refuse la permission, alors il sera hérité des Subject
s par défaut. Chaque SubjectCollection
définit ses propres valeurs par défaut. Le sujet par défaut global le plus faible peut être obtenu depuis le PermissionService
. Les plugins peuvent définir leurs propres permissions au SubjectData transitoire par défaut lors de chaque démarrage du serveur. Cela permet aux propriétaires du serveur de remplacer les valeurs par défaut définies par les plugins selon leurs besoins en utilisant le SubjectData
persistant par défaut. Si vous voulez fournir une directive de configuration pour les propriétaires de serveurs, utilisez les rôle-modèles de PermissionDescription
's à la place.
Avertissement
Vous devez y songer sérieusement avant d’accorder des permissions par défaut aux utilisateurs. En accordant des permissions en supposant que tous les propriétaires de serveurs vont vouloir ces valeurs par défaut (au moins la première fois que le plugin démarre) et que les exceptions nécessiteront que les propriétaires du serveur refusent explicitement les perrmissions (ce qui ne peut même pas être fait sans une implémentation d’un service de permissions personnalisées). Cela devrait correspondre en gros à un invité sur un monde lan en solo sans triche. Par exemple, un plugin de chat autoriserait à envoyer des messages dans le chat par défaut pour imiter le comportement du jeu de base pour des fonctionnalités qui ont été modifiées par le plugin.
Note
Les SubjectData
s persistants des Subject
s prennent le dessus sur ceux qui sont transitoires. Pour tous les autres Subject
s, les SubjectData
s transitoires prennent le dessus sur ceux qui sont persistants.
Si ni le Subject, ni aucun de ses parents, ni les valeurs par défaut n’assignent de valeur à une permission, alors elle est automatiquement refusée.
Note
Ordre de propriété dans l’ordre décroissant :
- Le Subject lui-même
Transitoire
Persistant
- Parents des Subjects
Transitoire
Persistant
- Valeurs par défaut de SubjectCollection
Persistant
Transitoire
- Valeurs par défaut de PermissionService
Persistant
Transitoire
Permission refusée
SubjectCollections
Un conteneur pour les sujets qui peut être utilisé pour obtenir un sujet par son nom. Voici les Subject Collections par défaut :
- Utilisateur
Contient tous les
Player
s connectés et lesUser
s déconnectés (au moins ceux avec des paramètres qui ne sont pas ceux par défaut).
- Groupe
Contient tous les groupes du
Subject
. Les groupes sont une façon simple de structures une arborescence d’héritage d’unSubject
en utilisant lesSubject
s nommés. Les groupes doivent être utilisés si un sous-ensemble spécifique deSubject
s possède des paramètres additionnels de permission comme une team, une faction, ou un rôle.
- Système
Contient tous les autres
Subject
s utilisés par le serveur, comme la console et les possibles consoles distantes.
- Bloc de Commande
Contient tous les
Subject
s pour les blocs de commande. Ils sont utiles si vous voulez exécuter unCommandBlock
uniquement avec les permissions du créateur.
- Modèle de Rôle
Contient tous les modèles de rôle qui sont utilisés dans les
PermissionDescription
s. Utile pour rechercher toutes les permissions recommandées pour un utilisateur. Ils ne doivent pas être utilisés pour l’héritage.
Note
Quand des SubjectCollection
s sont demandés pour un Subject
ils vont être créés automatiquement, si ils n’existent pas déjà. Cependant ils peuvent ne pas nécessairement apparaître dans getAllSubjects()
sauf si des valeurs qui ne sont pas celles par défaut sont définies.
SubjectData
Les SubjectData sont les stockages des permissions actuelles connectées au sujet. Il y a deux types de stockages de sujet :
Transitoire = Dure seulement pendant la durée de la session, n’est jamais sauvegardé
Régulier (persistant) = Peut être sauvegardé quelquepart, et donc être persistant et exister pour toujours. Il est recommandé aux
PermissionService
s d’implémenter un stockage persistant, cependant ce n’est pas obligatoire. Il peut aussi dépendre du type du sujet. Si il n’y a aucune persistance alors le stockage transitoire sera retourné dans les deux méthodes.
Les auteurs de plugins devraient envisager si il est nécessaire ou non de faire persister une valeur au moment de choisir entre eux.
Si c’est seulement pour une courte période (par exemple pendant un minijeu), alors utilisez celui qui est transitoire.
Si c’est pour une longue période ou pour toujours (par exemple une promotion au VIP), utilisez celui qui est régulier (persistant).
Veuillez consulter la section héritage si vous voulez en savoir plus à propos de l’hérédité et la priorité des SubjectData
s transitoires et persistants.
Options de Sujets
Les sujets fournissent aussi la possibilité de stocker des options en chaînes de caractères. Ce sont fondamentalement des pairs clé/valeur qui peuvent être assignés et hérités. Contrairement aux chaînes de caractères de permissions, les clés ne sont pas hiérarchiques et ne fournissent aucun mécanisme d’héritage eux-mêmes, mais les pairs clé/valeur eux-mêmes sont hérités des Subject
s parents dans la même manière que les permissions.
Contextes
Si vous considérez chaque permission à un privilège ou une capacité à pouvoir faire quelque chose, un Context représente les circonstances où ce privilège est utilisable.
Vous pourriez vouloir donner quelque chose à faire à une permission de Subject
, mais seulement lorsque le Subject
est dans un certain monde, ou dans une certaine région.
Les contextes sont accumulés par un Subject
, et sont alors utilisés par le PermissionService
pour décider de si le Subject
a un privilège ou non.
Sponge fournit quelques contextes par défaut, mais c’est généralement aux autres plugins de fournir des contextes additionnels au PermissionService, à travers un ContextCalculator.
Lors de la création de contextes pour vos propres pluginss, essayez d’éviter les conflits avec les autres plugins (par exemple en préfixant la clé de contexte avec l’id de votre plugin) à moins que ces contextes ne soient destinés à être partagés.
Note
Assurez-vous que votre ContextCalculator
réponde le plus vite possible puisqu’il sera fréquemment appelé.
Exemple
Votre ContextCalculator
peut ressembler à ceci :
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.context.ContextCalculator;
import org.spongepowered.api.service.permission.Subject;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
public class ExampleCalculator implements ContextCalculator<Subject> {
private static final Context IN_ANY_ARENA = new Context("myArenaPlugin-inAnyArena", "true");
private static final Context NOT_ANY_ARENA = new Context("myArenaPlugin-inAnyArena", "false");
private static final String ARENA_KEY = "myArenaPlugin-arena";
private final Map<UUID, String> playerArenas = new HashMap<>();
@Override
public void accumulateContexts(Subject calculable, Set<Context> accumulator) {
final Optional<CommandSource> commandSource = calculable.getCommandSource();
if (commandSource.isPresent() && commandSource.get() instanceof Player) {
final Player player = (Player) commandSource.get();
final UUID uuid = player.getUniqueId();
if (this.playerArenas.containsKey(uuid)) {
accumulator.add(IN_ANY_ARENA);
accumulator.add(new Context(ARENA_KEY, this.playerArenas.get(uuid)));
} else {
accumulator.add(NOT_ANY_ARENA);
}
}
}
@Override
public boolean matches(Context context, Subject subject) {
if (!context.equals(IN_ANY_ARENA) && !context.equals(NOT_ANY_ARENA) && !context.getKey().equals(ARENA_KEY)) {
return false;
}
final Optional<CommandSource> commandSource = subject.getCommandSource();
if (!commandSource.isPresent() || !(commandSource.get() instanceof Player)) {
return false;
}
final Player player = (Player) commandSource.get();
if (context.equals(IN_ANY_ARENA) && !this.playerArenas.containsKey(player.getUniqueId())) {
return false;
}
if (context.equals(NOT_ANY_ARENA) && this.playerArenas.containsKey(player.getUniqueId())) {
return false;
}
if (context.getKey().equals(ARENA_KEY)) {
if (!this.playerArenas.containsKey(player.getUniqueId())) {
return false;
}
if (!this.playerArenas.get(player.getUniqueId()).equals(context.getValue())) {
return false;
}
}
return true;
}
}
Le ContextCalculator
peut être enregistré via :
permissionService.registerContextCalculator(contextCalculator);