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 un usuario tiene el permiso myplugin.commands entonces automáticamente tiene todos los permisos secundarios, como myplugin.commands.teleport a menos que los permisos se eliminen explícitamente.

Nota

No existe el permiso comodín myplugin.commands. *. Utilice 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. PermissionDescriptions 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

Puede omitir las descripciones de escritura para algunos grupos de permisos parentales, como myplugin.commands.teleport.worlds o myplugin.commands, ya que su significado puede derivarse solo de la estructura de permisos y de los elementos 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 Subjects por defecto, pero hay muchos otros tipos de Subjects. 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 Subjects 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 Subjects” persistente SubjectDatas tiene prioridad sobre los transitorios. Para todos los demás Subjects, los transitorios SubjectDatas 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 Players en línea y todos Users 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 herencia Subjectutilizando Subjects. Los grupos deben usarse si un subconjunto específico de Subjects tiene configuraciones de permisos adicionales, como un equipo, facción o rol.

  • Sistema
    • Contiene otros Subjects usados por el servidor, como la consola y las posibles consolas remotas.

  • Bloque de Comandos
    • Contiene todos los Subjects para bloques de comandos. Estos son útiles si desea ejecutar un CommandBlock solo con los permisos del creador.

  • Plantilla de Rol
    • Contiene todos los temas de plantilla de rol que se usan en PermissionDescriptions. Útil para buscar todos los permisos recomendados para un usuario. Estos no deberían usarse para herencia.

Nota

Cuando se pregunta a SubjectCollections por un Subject, se crearán automáticamente, si es que todavía no existen. Sin embargo, es posible que no aparezcan necesariamente en ``getAllSubjects () ``a menos que se establezcan valores no predeterminados.

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 PermissionServices 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 SubjectDatas 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 Subjects 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);

Para Modificar Fragua

Si es el autor de una modificación de Fragua y no está utilizando el nuevo Forge PermissionsAPI pero está haciendo comprobaciones de OP, entonces ya está en el camino correcto para que Sponge recoja los permisos.

La forma más sencilla de crear un permiso de Sponge en una modificación de Fragua sin depender de SpongeAPI es usar el método provisto por el código Vanilla Minecraft en ICommandSender, es decir ICommandSender.canCommandSenderUseCommand (int permLevel, String commandName). La Cadena transferida a ese método no tiene ningún uso en un entorno de Vanilla Forge, pero cuando se agrega SpongeForge, automáticamente toma esa Cadena y lo convierte en un permiso de trabajo.

Ejemplo

public class AwesomeBlock extends Block {
    @Override
    public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ) {
        if (player.canCommandSenderUseCommand(4, "examplemod.awesomeblock.interact")) {
            // Do cool stuff
            return true;
        }
        return false;
    }
}

Como puede ver, simplemente verificamos el nivel OP y pasamos una Cadena arbitraria que queremos usar como permiso cuando se usa Sponge. Cuando la Fragua se usa el jugador simplemente requiere el nivel OP, por lo que pasar un valor de 0 permitiría a todos los usuarios interactuar con el bloque, pero cuando se agrega SpongeForge requieren el nodo de permiso de examplemod.awesomeblock.interact. Se recomienda seguir la estructura de permisos como se describe arriba. La herencia de permisos también se aplica a estos controles.

Nota

El nombre de SRG para este método es func_70003_b.