Permisos
Permiso
Un permiso es una clave de cadena jerárquica no sensible a mayúsculas y minúsculas que es utilizado para determinar si un sujeto puede hacer una acción específica o no. La cuerda se divide en partes separadas usando el carácter de punto. Los permisos deberían estructurarse así.
<PluginID>.<MainGroup>.<Subgroup1>...
Los caracteres permitidos son:
«A» - «Z»
«a» - «z»
«0» - «9»
«_»
«-»
«.»
Herencia
Si el usuario tiene el permiso myPlugin.commands
luego ellos automaticamente tienen toods los sub permisos como ``myPlugin.commands.teleport``a menos que los permisos esten explicitamente eliminados.
Nota
No hay ninguna cosa como myPlugin.commands.*
permiso comodín. Use myPlugin.commands
para eso.
Estructura-Ejemplo
El siguiente ejemplo muestra una forma posible de estructurar permisos, pero no es necesario seguir esta estructura.
myPlugin
Concede acceso full a todos los permisos del complemento.
myPlugin.commands
Concede acceso full a todos los permisos del complemento.
myPlugin.commands.teleport.execute
Solo otorga al usuario el permiso para ejecutar el comando. Sin este permiso, no puede ejecutar el comando incluso si tiene otros permisos de “teleport”. (Con este permiso, solo el usuario podría teleportarse a otros en su mundo actual)
myPlugin.commands.teleport.all
Solo otorga al usuario el permiso para teletransportarse a todos los jugadores a la vez.
myPlugin.commands.teleport.worlds
Solo otorga al usuario el permiso para teletransportarse a todos los mundos.
myPlugin.commands.teleport.worlds.mynetherworld
Solo otorga al usuario el permiso para teletransportarse a * mynetherworld *.
PermissionDescription
El :javadoc: PermisionDescription es una utilidad que está destinada a proporcionar al propietario del servidor los detalles sobre un determinado permiso. PermissionDescription
s es una función opcional a la que PermissionService puede proporcionar. La creación de una descripción de permiso no tiene ningún impacto sobre si existe un permiso, quién tiene acceso o cuál es su valor predeterminado.
La descripción consiste en:
el Id de permiso de destino
a descripción del Texto
uno o más roles asignados
el plugin propietario
Si tiene un elemento dinámico como World
o ItemType
, puede usar <TemplateParts>
.
Ejemplo de Uso
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();
}
Resultado Simple
myPlugin.commands.teleport.execute
Description: Allows the user to execute the teleport command.
Role: user
Owner: MyPlugin v1.2.3
Resultado de la Plantilla
myPlugin.commands.teleport.worlds.<World>
Description: Allows the user to teleport to the world <World>.
Role: staff
Owner: MyPlugin v1.2.3
Truco
Usted debe saltar las descripciones escritas para algún grupo de permisos de parientes como myPlugin.commands.teleport.worlds
o ``myPlugin.commands``como su significado puede ser derivado de la estructura del permiso y de los niños solos definidos.
Tema
Un :javadoc: Subject es un titular de permisos asignados. Se puede obtener de PermissionService
a través de :javadoc: SubjectCollections. :javadoc: CommandSources como Players son Subject
s por defecto, pero hay muchos otros tipos de Subject
s. Todo lo que tiene permisos es un Sujeto, incluso si solo delega las verificaciones en un Asunto contenido. Los permisos pueden ser otorgados o denegados a un Sujeto. Si un permiso no se otorga ni se niega, su configuración se heredará. Ver herencia. Los sujetos proporcionan métodos para verificar si tienen cierto permiso o no. Los complementos que usan este método solo deben consultar el permiso específico que desean verificar. Es tarea de PermissionService respetar el permiso y la herencia del sujeto.
Ejemplo
El siguiente ejemplo podría usarse para verificar si el reproductor tiene permiso para ejecutar el comando de teletransporte.
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()));
}
Herencia
Si un Subject
tiene un permiso asignado, usará ese valor. De lo contrario, se heredará de cualquier padre Subject
. No importa qué tipo de padre (por ejemplo, grupo o jugador) Subject
pueda ser.
Si ni el subject en sí ni ninguno de los padres otorgan o niegan un permiso, se heredará del Subject
s predeterminado. Cada SubjectCollection
define sus propios valores predeterminados. El sujeto predeterminado global y más débil se puede obtener de PermissionService
. Los complementos pueden definir sus propios permisos para el transitorio predeterminado :javadoc: SubjectData durante cada inicio del servidor. Esto permite a los propietarios del servidor sobrescribir los valores predeterminados definidos por los complementos de acuerdo con sus necesidades utilizando el SubjectData
persistente por defecto. Si desea proporcionar una guía de configuración para los propietarios de servidores, use las plantillas de roles de PermissionDescription
's en su lugar.
Advertencia
Debe pensar detenidamente antes de otorgar permisos predeterminados a los usuarios. Al otorgar los permisos, asume que todos los propietarios de los servidores querrán estos valores predeterminados (al menos la primera vez que se ejecuta el complemento) y que las excepciones requerirán que los propietarios del servidor nieguen explícitamente los permisos (lo cual no se puede hacer sin un servicio de permisos personalizado de implementación). Esto debería corresponder aproximadamente a un invitado en un mundo lan de un jugador sin trampas. Por ejemplo, un complemento de chat permitiría enviar mensajes de chat de forma predeterminada para imitar el comportamiento del juego de vanilla para las características que fueron modificadas por el complemento.
Nota
El predeterminado Subject
s” persistente SubjectData
s tiene prioridad sobre los transitorios. Para todos los demás Subject
s, los transitorios SubjectData
s tienen prioridad sobre los persistentes.
Si ni el Subject, ni ninguno de sus padres, ni los valores predeterminados asignan un valor a un permiso, se denegará automáticamente.
Nota
Orden de precedencia en orden descendente:
- Sujeto mismo
Transitorio
Persistente
- Sujetos Primarios
Transitorio
Persistente
- Valores Predeterminados de SubjectCollection
Persistente
Transitorio
- Valores Predeterminados de PermissionService
Persistente
Transitorio
Denegar permiso
SubjectCollections
Un contenedor para sujetos que pueden usarse para obtener un Sujeto por nombre. Estas son las colecciones de sujetos predeterminados:
- Usuario
Contiene todos los
Player
s en línea y todosUser
s fuera de línea (al menos aquellos con configuraciones no predeterminadas).
- Grupo
Contiene todo el grupo
Sujeto
. Los grupos son una forma simple de estructurar un árbol de herenciaSubject
utilizandoSubject
s. Los grupos deben usarse si un subconjunto específico deSubject
s tiene configuraciones de permisos adicionales, como un equipo, facción o rol.
- Sistema
Contiene otros
Subject
s usados por el servidor, como la consola y las posibles consolas remotas.
- Bloque de Comandos
Contiene todos los
Subject
s para bloques de comandos. Estos son útiles si desea ejecutar unCommandBlock
solo con los permisos del creador.
- Plantilla de Rol
Contiene todos los temas de plantilla de rol que se usan en
PermissionDescription
s. Útil para buscar todos los permisos recomendados para un usuario. Estos no deberían usarse para herencia.
SubjectData
SubjectData son las tiendas de permisos reales conectadas al Subject (tema). Hay dos tipos de tiendas de Subject:
Transitorio = dura solamente la duración de la sesión, nunca se guarda
Regular (persistente) = Se puede guardar en algún lugar, y por lo tanto persistirá y existirá para siempre. Se recomienda para
PermissionService
s implementar una tienda persistente, sin embargo, no es un requisito. También podría depender del tipo de subject. Si no hay persistencia, la tienda transitoria se devolverá en ambos métodos.
Los autores de Plugin (complementos) deben considerar si es necesario mantener un valor al elegir entre ellos.
Si solo es por un tiempo corto (por ejemplo, durante un minijuego), utilice el transitorio.
Si es por un tiempo prolongado o por siempre (por ejemplo, una promoción para VIP), use el regular (persistente).
Por favor consulte la sección Herencia si desea saber más acerca de la herencia y la precedencia de los SubjectData
s transitorios y persistentes.
Opciones de Subject (Tema)
Los subjects también brindan la posibilidad de almacenar opciones de cadenas. Estos son básicamente pares de valores clave que se pueden asignar y heredar. A diferencia de las cadenas de permisos, las claves no son jerárquicas y no proporcionan ningún mecanismo de herencia en sí mismas, pero los pares de valores clave se heredan del padre Subject
s de la misma manera que los permisos.
Contextos
Si considera cada permiso para un privilegio o habilidad para poder hacer algo, a :javadoc: Context son las circunstancias donde ese privilegio es utilizable.
Es posible que desees otorgar un permiso Subject
para hacer algo, pero solo cuando Subject
esté en cierto mundo o en cierta región.
Los contextos son acumulados por un Subject
, y luego son usados por PermissionService
para decidir si Subject
tiene un privilegio o no.
Sponge proporciona algunos contextos por defecto, pero generalmente se debe a otros complementos para proporcionar contextos adicionales al PermissionService, a través de ContextCalculator.
Al crear contextos para su propio complemento (plugin), intente evitar conflictos con otros complementos (por ejemplo, prefijando la clave de contexto con su id de complemento), a menos que estos contextos estén destinados a ser compartidos.
Nota
Por favor, asegúrese de que su ContextCalculator
responda tan rápido como sea posible, ya que se llamará con frecuencia.
Ejemplo
Su ContextCalculator
puede verse de esta forma:
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;
}
}
El ContextCalculator
se puede registrar por medio de:
permissionService.registerContextCalculator(contextCalculator);