Introduce parentPermission for commands

This commit is contained in:
Him188 2020-09-09 10:02:56 +08:00
parent 44ef4e7c56
commit 2926e55590
16 changed files with 60 additions and 33 deletions

View File

@ -105,7 +105,7 @@ public abstract class AbstractCommand
public override val owner: CommandOwner, public override val owner: CommandOwner,
vararg names: String, vararg names: String,
description: String = "<no description available>", description: String = "<no description available>",
basePermission: PermissionId? = null, parentPermission: PermissionId = owner.basePermission,
/** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */ /** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */
public override val prefixOptional: Boolean = false public override val prefixOptional: Boolean = false
) : Command { ) : Command {
@ -116,5 +116,5 @@ public abstract class AbstractCommand
}.toTypedArray() }.toTypedArray()
@OptIn(ExperimentalPermission::class) @OptIn(ExperimentalPermission::class)
public override val permission: Permission by lazy { createCommandPermission(basePermission) } public override val permission: Permission by lazy { createCommandPermission(parentPermission) }
} }

View File

@ -10,6 +10,7 @@
package net.mamoe.mirai.console.command package net.mamoe.mirai.console.command
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregisterAllCommands import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregisterAllCommands
import net.mamoe.mirai.console.permission.BasePermission
import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.ExperimentalPermission
import net.mamoe.mirai.console.permission.PermissionId import net.mamoe.mirai.console.permission.PermissionId
import net.mamoe.mirai.console.permission.PermissionIdNamespace import net.mamoe.mirai.console.permission.PermissionIdNamespace
@ -23,12 +24,21 @@ import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
* *
* @see JvmPlugin 是一个 [CommandOwner] * @see JvmPlugin 是一个 [CommandOwner]
*/ */
public interface CommandOwner : PermissionIdNamespace public interface CommandOwner : PermissionIdNamespace {
/**
* [PermissionIdNamespace] 拥有的指令都默认将 [basePermission] 作为父权限.
*
* TODO document
*/
public val basePermission: PermissionId
}
/** /**
* 代表控制台所有者. 所有的 mirai-console 内建的指令都属于 [ConsoleCommandOwner]. * 代表控制台所有者. 所有的 mirai-console 内建的指令都属于 [ConsoleCommandOwner].
*/ */
internal object ConsoleCommandOwner : CommandOwner { internal object ConsoleCommandOwner : CommandOwner {
override val basePermission: PermissionId get() = BasePermission.id
@ExperimentalPermission @ExperimentalPermission
override fun permissionId(id: String): PermissionId = PermissionId("console", id) override fun permissionId(id: String): PermissionId = PermissionId("console", id)
} }

View File

@ -86,10 +86,10 @@ public abstract class CompositeCommand(
owner: CommandOwner, owner: CommandOwner,
vararg names: String, vararg names: String,
description: String = "no description available", description: String = "no description available",
basePermission: PermissionId? = null, parentPermission: PermissionId = owner.basePermission,
prefixOptional: Boolean = false, prefixOptional: Boolean = false,
overrideContext: CommandArgumentContext = EmptyCommandArgumentContext overrideContext: CommandArgumentContext = EmptyCommandArgumentContext
) : Command, AbstractReflectionCommand(owner, names, description, basePermission, prefixOptional), ) : Command, AbstractReflectionCommand(owner, names, description, parentPermission, prefixOptional),
CommandArgumentContextAware { CommandArgumentContextAware {
/** /**

View File

@ -43,13 +43,13 @@ public abstract class RawCommand(
public override val usage: String = "<no usages given>", public override val usage: String = "<no usages given>",
/** 指令描述, 用于显示在 [BuiltInCommands.Help] */ /** 指令描述, 用于显示在 [BuiltInCommands.Help] */
public override val description: String = "<no descriptions given>", public override val description: String = "<no descriptions given>",
/** 指令权限 */ /** 指令权限 */
basePermission: PermissionId? = null, parentPermission: PermissionId = owner.basePermission,
/** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */ /** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */
public override val prefixOptional: Boolean = false public override val prefixOptional: Boolean = false
) : Command { ) : Command {
@OptIn(ExperimentalPermission::class) @OptIn(ExperimentalPermission::class)
public override val permission: Permission by lazy { createCommandPermission(basePermission) } public override val permission: Permission by lazy { createCommandPermission(parentPermission) }
/** /**
* 在指令被执行时调用. * 在指令被执行时调用.

View File

@ -52,7 +52,7 @@ public abstract class SimpleCommand(
owner: CommandOwner, owner: CommandOwner,
vararg names: String, vararg names: String,
description: String = "no description available", description: String = "no description available",
basePermission: PermissionId? = null, basePermission: PermissionId = owner.basePermission,
prefixOptional: Boolean = false, prefixOptional: Boolean = false,
overrideContext: CommandArgumentContext = EmptyCommandArgumentContext overrideContext: CommandArgumentContext = EmptyCommandArgumentContext
) : Command, AbstractReflectionCommand(owner, names, description, basePermission, prefixOptional), ) : Command, AbstractReflectionCommand(owner, names, description, basePermission, prefixOptional),

View File

@ -72,8 +72,8 @@ import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
public abstract class JCompositeCommand @JvmOverloads constructor( public abstract class JCompositeCommand @JvmOverloads constructor(
owner: CommandOwner, owner: CommandOwner,
vararg names: String, vararg names: String,
basePermission: PermissionId? = null, parentPermission: PermissionId = owner.basePermission,
) : CompositeCommand(owner, *names, basePermission = basePermission) { ) : CompositeCommand(owner, *names, parentPermission = parentPermission) {
/** 指令描述, 用于显示在 [BuiltInCommands.Help] */ /** 指令描述, 用于显示在 [BuiltInCommands.Help] */
public final override var description: String = "<no descriptions given>" public final override var description: String = "<no descriptions given>"
protected set protected set

View File

@ -53,7 +53,7 @@ public abstract class JRawCommand @JvmOverloads constructor(
public override val owner: CommandOwner, public override val owner: CommandOwner,
/** 指令名. 需要至少有一个元素. 所有元素都不能带有空格 */ /** 指令名. 需要至少有一个元素. 所有元素都不能带有空格 */
public override vararg val names: String, public override vararg val names: String,
basePermission: PermissionId? = null, parentPermission: PermissionId = owner.basePermission,
) : Command { ) : Command {
/** 用法说明, 用于发送给用户 */ /** 用法说明, 用于发送给用户 */
public override var usage: String = "<no usages given>" public override var usage: String = "<no usages given>"
@ -64,7 +64,7 @@ public abstract class JRawCommand @JvmOverloads constructor(
protected set protected set
/** 指令权限 */ /** 指令权限 */
public final override var permission: Permission = createCommandPermission(basePermission) public final override var permission: Permission = createCommandPermission(parentPermission)
protected set protected set
/** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */ /** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */

View File

@ -48,13 +48,13 @@ internal abstract class AbstractReflectionCommand @JvmOverloads constructor(
owner: CommandOwner, owner: CommandOwner,
names: Array<out String>, names: Array<out String>,
description: String = "<no description available>", description: String = "<no description available>",
basePermission: PermissionId? = null, parentPermission: PermissionId = owner.basePermission,
prefixOptional: Boolean = false prefixOptional: Boolean = false
) : Command, AbstractCommand( ) : Command, AbstractCommand(
owner, owner,
names = names, names = names,
description = description, description = description,
basePermission = basePermission, parentPermission = parentPermission,
prefixOptional = prefixOptional prefixOptional = prefixOptional
), CommandArgumentContextAware { ), CommandArgumentContextAware {
internal abstract val subCommandAnnotationResolver: SubCommandAnnotationResolver internal abstract val subCommandAnnotationResolver: SubCommandAnnotationResolver
@ -74,7 +74,7 @@ internal abstract class AbstractReflectionCommand @JvmOverloads constructor(
internal val defaultSubCommand: DefaultSubCommandDescriptor by lazy { internal val defaultSubCommand: DefaultSubCommandDescriptor by lazy {
DefaultSubCommandDescriptor( DefaultSubCommandDescriptor(
"", "",
createCommandPermission(basePermission), createCommandPermission(parentPermission),
onCommand = { sender: CommandSender, args: MessageChain -> onCommand = { sender: CommandSender, args: MessageChain ->
sender.onDefault(args) sender.onDefault(args)
} }

View File

@ -139,15 +139,12 @@ internal fun Group.fuzzySearchMember(
} }
@OptIn(ExperimentalPermission::class) @OptIn(ExperimentalPermission::class)
internal fun Command.createCommandPermission(basePermission: PermissionId?): Permission { internal fun Command.createCommandPermission(parent: PermissionId): Permission {
return PermissionService.INSTANCE.register(owner.permissionId(primaryName), description, basePermission) return PermissionService.INSTANCE.register(owner.permissionId(primaryName), description, parent)
} }
//// internal //// internal
@JvmSynthetic
internal inline fun <reified T> List<T>.dropToTypedArray(n: Int): Array<T> = Array(size - n) { this[n + it] }
@OptIn(ExperimentalPermission::class) @OptIn(ExperimentalPermission::class)
@JvmSynthetic @JvmSynthetic
@Throws(CommandExecutionException::class) @Throws(CommandExecutionException::class)

View File

@ -17,11 +17,14 @@ import net.mamoe.mirai.console.data.runCatchingLog
import net.mamoe.mirai.console.internal.data.mkdir import net.mamoe.mirai.console.internal.data.mkdir
import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.ExperimentalPermission
import net.mamoe.mirai.console.permission.PermissionId import net.mamoe.mirai.console.permission.PermissionId
import net.mamoe.mirai.console.permission.PermissionService
import net.mamoe.mirai.console.permission.allocatePermissionIdForPlugin
import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.Plugin
import net.mamoe.mirai.console.plugin.PluginManager import net.mamoe.mirai.console.plugin.PluginManager
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.safeLoader import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.safeLoader
import net.mamoe.mirai.console.plugin.ResourceContainer.Companion.asResourceContainer import net.mamoe.mirai.console.plugin.ResourceContainer.Companion.asResourceContainer
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
import net.mamoe.mirai.console.plugin.name
import net.mamoe.mirai.console.util.NamedSupervisorJob import net.mamoe.mirai.console.util.NamedSupervisorJob
import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.MiraiLogger
import java.io.File import java.io.File
@ -40,6 +43,14 @@ internal abstract class JvmPluginInternal(
parentCoroutineContext: CoroutineContext parentCoroutineContext: CoroutineContext
) : JvmPlugin, CoroutineScope { ) : JvmPlugin, CoroutineScope {
@OptIn(ExperimentalPermission::class)
final override val basePermission: PermissionId by lazy {
PermissionService.INSTANCE.register(
PermissionService.INSTANCE.allocatePermissionIdForPlugin(name, "*"),
"The base permission"
).id
}
final override var isEnabled: Boolean = false final override var isEnabled: Boolean = false
private val resourceContainerDelegate by lazy { this::class.java.classLoader.asResourceContainer() } private val resourceContainerDelegate by lazy { this::class.java.classLoader.asResourceContainer() }
@ -99,6 +110,7 @@ internal abstract class JvmPluginInternal(
} }
internal fun internalOnEnable(): Boolean { internal fun internalOnEnable(): Boolean {
basePermission
if (!firstRun) refreshCoroutineContext() if (!firstRun) refreshCoroutineContext()
kotlin.runCatching { kotlin.runCatching {
onEnable() onEnable()
@ -124,6 +136,7 @@ internal abstract class JvmPluginInternal(
internal val _intrinsicCoroutineContext: CoroutineContext by lazy { internal val _intrinsicCoroutineContext: CoroutineContext by lazy {
CoroutineName("Plugin $dataHolderName") CoroutineName("Plugin $dataHolderName")
} }
@JvmField @JvmField
internal val coroutineContextInitializer = { internal val coroutineContextInitializer = {
CoroutineExceptionHandler { context, throwable -> CoroutineExceptionHandler { context, throwable ->

View File

@ -20,12 +20,12 @@ public abstract class AbstractConcurrentPermissionService<P : Permission> : Perm
protected abstract fun createPermission( protected abstract fun createPermission(
id: PermissionId, id: PermissionId,
description: String, description: String,
base: PermissionId? base: PermissionId = BasePermission.id
): P ): P
override fun get(id: PermissionId): P? = permissions[id] override fun get(id: PermissionId): P? = permissions[id]
override fun register(id: PermissionId, description: String, base: PermissionId?): P { override fun register(id: PermissionId, description: String, base: PermissionId): P {
grantedPermissionsMap[id] = CopyOnWriteArrayList() // mutations are not quite often performed grantedPermissionsMap[id] = CopyOnWriteArrayList() // mutations are not quite often performed
val instance = createPermission(id, description, base) val instance = createPermission(id, description, base)
if (permissions.putIfAbsent(id, instance) != null) { if (permissions.putIfAbsent(id, instance) != null) {

View File

@ -32,7 +32,7 @@ public object AllGrantPermissionService : PermissionService<PermissionImpl> {
override fun register( override fun register(
id: PermissionId, id: PermissionId,
description: String, description: String,
base: PermissionId? base: PermissionId
): PermissionImpl { ): PermissionImpl {
val new = PermissionImpl(id, description, base) val new = PermissionImpl(id, description, base)
if (all.putIfAbsent(id, new) != null) { if (all.putIfAbsent(id, new) != null) {
@ -48,7 +48,7 @@ public object AllGrantPermissionService : PermissionService<PermissionImpl> {
override fun grant(permissibleIdentifier: PermissibleIdentifier, permission: PermissionImpl) { override fun grant(permissibleIdentifier: PermissibleIdentifier, permission: PermissionImpl) {
} }
override fun testPermission(permissibleIdentifier: PermissibleIdentifier, permission: PermissionImpl): Boolean = override fun testPermission(permissibleIdentifier: PermissibleIdentifier, permissionId: PermissionId): Boolean =
true true
override fun deny(permissibleIdentifier: PermissibleIdentifier, permission: PermissionImpl) { override fun deny(permissibleIdentifier: PermissibleIdentifier, permission: PermissionImpl) {
@ -64,7 +64,7 @@ public object AllDenyPermissionService : PermissionService<PermissionImpl> {
override fun register( override fun register(
id: PermissionId, id: PermissionId,
description: String, description: String,
base: PermissionId? base: PermissionId
): PermissionImpl { ): PermissionImpl {
val new = PermissionImpl(id, description, base) val new = PermissionImpl(id, description, base)
if (all.putIfAbsent(id, new) != null) { if (all.putIfAbsent(id, new) != null) {
@ -80,7 +80,7 @@ public object AllDenyPermissionService : PermissionService<PermissionImpl> {
override fun grant(permissibleIdentifier: PermissibleIdentifier, permission: PermissionImpl) { override fun grant(permissibleIdentifier: PermissibleIdentifier, permission: PermissionImpl) {
} }
override fun testPermission(permissibleIdentifier: PermissibleIdentifier, permission: PermissionImpl): Boolean = override fun testPermission(permissibleIdentifier: PermissibleIdentifier, permissionId: PermissionId): Boolean =
false false
override fun deny(permissibleIdentifier: PermissibleIdentifier, permission: PermissionImpl) { override fun deny(permissibleIdentifier: PermissibleIdentifier, permission: PermissionImpl) {
@ -100,7 +100,7 @@ internal object BuiltInPermissionService : AbstractConcurrentPermissionService<P
override val grantedPermissionsMap: MutableMap<PermissionId, MutableCollection<PermissibleIdentifier>> override val grantedPermissionsMap: MutableMap<PermissionId, MutableCollection<PermissibleIdentifier>>
get() = config.grantedPermissionMap as MutableMap<PermissionId, MutableCollection<PermissibleIdentifier>> get() = config.grantedPermissionMap as MutableMap<PermissionId, MutableCollection<PermissibleIdentifier>>
override fun createPermission(id: PermissionId, description: String, base: PermissionId?): PermissionImpl = override fun createPermission(id: PermissionId, description: String, base: PermissionId): PermissionImpl =
PermissionImpl(id, description, base) PermissionImpl(id, description, base)
internal val config: ConcurrentSaveData<PermissionImpl> = internal val config: ConcurrentSaveData<PermissionImpl> =

View File

@ -14,7 +14,9 @@ import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
/** /**
* 一个权限节点 * 一个权限节点.
*
* [PermissionService] 实现不同, [Permission] 可能会有多种实例. 但一个权限总是拥有确定的 [id]
*/ */
@ExperimentalPermission @ExperimentalPermission
public interface Permission { public interface Permission {
@ -29,10 +31,9 @@ public interface Permission {
@ExperimentalPermission @ExperimentalPermission
public object BasePermission : public object BasePermission :
Permission { Permission {
override val id: PermissionId = PermissionId("console", "base") override val id: PermissionId = PermissionId("*", "*")
override val description: String get() = "The parent of any permission" override val description: String get() = "The parent of any permission"
override val parent: PermissionId get() = id override val parent: PermissionId get() = id
} }
@ConsoleExperimentalAPI @ConsoleExperimentalAPI

View File

@ -16,6 +16,9 @@ import kotlinx.serialization.builtins.serializer
import net.mamoe.mirai.console.internal.data.map import net.mamoe.mirai.console.internal.data.map
/**
* [PermissionId] [Permission] 唯一对应.
*/
@Serializable @Serializable
@ExperimentalPermission @ExperimentalPermission
public data class PermissionId( public data class PermissionId(

View File

@ -43,7 +43,7 @@ public interface PermissionService<P : Permission> {
public fun register( public fun register(
id: PermissionId, id: PermissionId,
description: String, description: String,
base: PermissionId? = null base: PermissionId = BasePermission.id
): P ): P
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -60,6 +60,9 @@ public interface PermissionService<P : Permission> {
} }
} }
internal fun PermissionService<*>.allocatePermissionIdForPlugin(name: String, id: String) =
PermissionId("plugin.${name.toLowerCase()}", id.toLowerCase())
@ExperimentalPermission @ExperimentalPermission
public fun PermissionId.findCorrespondingPermission(): Permission? = PermissionService.INSTANCE[this] public fun PermissionId.findCorrespondingPermission(): Permission? = PermissionService.INSTANCE[this]

View File

@ -27,7 +27,7 @@ public interface PluginDescription {
public val kind: PluginKind public val kind: PluginKind
/** /**
* 插件名称. 不允许存在 ":". * 插件名称. 不允许存在 ":", 推荐全英文.
* *
* 插件名称不能完全是以下其中一种. * 插件名称不能完全是以下其中一种.
* - console * - console