Use Permission for Permission.parent

This commit is contained in:
Him188 2020-09-10 19:53:27 +08:00
parent dd9cc3c706
commit cea884c3d7
18 changed files with 151 additions and 113 deletions

View File

@ -16,17 +16,13 @@ import net.mamoe.mirai.Bot
import net.mamoe.mirai.alsoLogin import net.mamoe.mirai.alsoLogin
import net.mamoe.mirai.console.MiraiConsole import net.mamoe.mirai.console.MiraiConsole
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register
import net.mamoe.mirai.console.command.description.PermissibleIdentifierArgumentParser import net.mamoe.mirai.console.command.description.*
import net.mamoe.mirai.console.command.description.PermissionIdArgumentParser
import net.mamoe.mirai.console.command.description.buildCommandArgumentContext
import net.mamoe.mirai.console.internal.command.CommandManagerImpl import net.mamoe.mirai.console.internal.command.CommandManagerImpl
import net.mamoe.mirai.console.internal.command.CommandManagerImpl.allRegisteredCommands import net.mamoe.mirai.console.internal.command.CommandManagerImpl.allRegisteredCommands
import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip
import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.*
import net.mamoe.mirai.console.permission.PermissibleIdentifier
import net.mamoe.mirai.console.permission.PermissionId
import net.mamoe.mirai.console.permission.PermissionService
import net.mamoe.mirai.console.permission.PermissionService.Companion.denyPermission import net.mamoe.mirai.console.permission.PermissionService.Companion.denyPermission
import net.mamoe.mirai.console.permission.PermissionService.Companion.findCorrespondingPermissionOrFail
import net.mamoe.mirai.console.permission.PermissionService.Companion.getGrantedPermissions import net.mamoe.mirai.console.permission.PermissionService.Companion.getGrantedPermissions
import net.mamoe.mirai.console.permission.PermissionService.Companion.grantPermission import net.mamoe.mirai.console.permission.PermissionService.Companion.grantPermission
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
@ -51,6 +47,7 @@ internal interface BuiltInCommandInternal : Command
*/ */
@ConsoleExperimentalAPI @ConsoleExperimentalAPI
@Suppress("unused") @Suppress("unused")
@OptIn(ExperimentalPermission::class)
public object BuiltInCommands { public object BuiltInCommands {
public val all: Array<out Command> by lazy { public val all: Array<out Command> by lazy {
@ -63,9 +60,10 @@ public object BuiltInCommands {
} }
} }
public object Help : SimpleCommand( public object HelpCommand : SimpleCommand(
ConsoleCommandOwner, "help", ConsoleCommandOwner, "help",
description = "Command list" description = "Command list",
parentPermission = RootConsoleBuiltInPermission,
), BuiltInCommand { ), BuiltInCommand {
@Handler @Handler
public suspend fun CommandSender.handle() { public suspend fun CommandSender.handle() {
@ -82,9 +80,10 @@ public object BuiltInCommands {
}) })
} }
public object Stop : SimpleCommand( public object StopCommand : SimpleCommand(
ConsoleCommandOwner, "stop", "shutdown", "exit", ConsoleCommandOwner, "stop", "shutdown", "exit",
description = "Stop the whole world." description = "Stop the whole world.",
parentPermission = RootConsoleBuiltInPermission,
), BuiltInCommand { ), BuiltInCommand {
private val closingLock = Mutex() private val closingLock = Mutex()
@ -117,9 +116,10 @@ public object BuiltInCommands {
} }
} }
public object Login : SimpleCommand( public object LoginCommand : SimpleCommand(
ConsoleCommandOwner, "login", "登录", ConsoleCommandOwner, "login", "登录",
description = "Log in a bot account." description = "Log in a bot account.",
parentPermission = RootConsoleBuiltInPermission,
), BuiltInCommand { ), BuiltInCommand {
@Handler @Handler
public suspend fun CommandSender.handle(id: Long, password: String) { public suspend fun CommandSender.handle(id: Long, password: String) {
@ -145,23 +145,28 @@ public object BuiltInCommands {
} }
@OptIn(ExperimentalPermission::class) @OptIn(ExperimentalPermission::class)
public object Permission : CompositeCommand( public object PermissionCommand : CompositeCommand(
ConsoleCommandOwner, "permission", "权限", ConsoleCommandOwner, "permission", "权限", "perm",
description = "Manage permissions", description = "Manage permissions",
overrideContext = buildCommandArgumentContext { overrideContext = buildCommandArgumentContext {
PermissibleIdentifier::class with PermissibleIdentifierArgumentParser PermissibleIdentifier::class with PermissibleIdentifierArgumentParser
PermissionId::class with PermissionIdArgumentParser Permission::class with PermissionIdArgumentParser.map { id ->
kotlin.runCatching {
id.findCorrespondingPermissionOrFail()
}.getOrElse { illegalArgument("指令不存在: $id", it) }
} }
},
parentPermission = RootConsoleBuiltInPermission,
), BuiltInCommand { ), BuiltInCommand {
// TODO: 2020/9/10 improve Permission command // TODO: 2020/9/10 improve Permission command
@SubCommand @SubCommand
public suspend fun CommandSender.grant(target: PermissibleIdentifier, permission: PermissionId) { public suspend fun CommandSender.grant(target: PermissibleIdentifier, permission: Permission) {
target.grantPermission(permission) target.grantPermission(permission)
sendMessage("OK") sendMessage("OK")
} }
@SubCommand @SubCommand
public suspend fun CommandSender.deny(target: PermissibleIdentifier, permission: PermissionId) { public suspend fun CommandSender.deny(target: PermissibleIdentifier, permission: Permission) {
target.denyPermission(permission) target.denyPermission(permission)
sendMessage("OK") sendMessage("OK")
} }

View File

@ -19,7 +19,6 @@ import net.mamoe.mirai.console.internal.command.createOrFindCommandPermission
import net.mamoe.mirai.console.internal.command.isValidSubName import net.mamoe.mirai.console.internal.command.isValidSubName
import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.ExperimentalPermission
import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.console.permission.Permission
import net.mamoe.mirai.console.permission.PermissionId
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.SingleMessage import net.mamoe.mirai.message.data.SingleMessage
@ -107,7 +106,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>",
parentPermission: PermissionId = owner.basePermission, parentPermission: Permission = owner.parentPermission,
/** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */ /** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */
public override val prefixOptional: Boolean = false public override val prefixOptional: Boolean = false
) : Command { ) : Command {

View File

@ -10,10 +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.ExperimentalPermission import net.mamoe.mirai.console.permission.*
import net.mamoe.mirai.console.permission.PermissionId
import net.mamoe.mirai.console.permission.PermissionIdNamespace
import net.mamoe.mirai.console.permission.RootPermission
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
/** /**
@ -27,12 +24,12 @@ import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
@OptIn(ExperimentalPermission::class) @OptIn(ExperimentalPermission::class)
public interface CommandOwner : PermissionIdNamespace { public interface CommandOwner : PermissionIdNamespace {
/** /**
* [PermissionIdNamespace] 拥有的指令都默认将 [basePermission] 作为父权限. * [PermissionIdNamespace] 拥有的指令都默认将 [parentPermission] 作为父权限.
* *
* TODO document * TODO document
*/ */
@ExperimentalPermission @ExperimentalPermission
public val basePermission: PermissionId public val parentPermission: Permission
} }
/** /**
@ -40,8 +37,8 @@ public interface CommandOwner : PermissionIdNamespace {
*/ */
internal object ConsoleCommandOwner : CommandOwner { internal object ConsoleCommandOwner : CommandOwner {
@ExperimentalPermission @ExperimentalPermission
override val basePermission: PermissionId override val parentPermission: Permission
get() = RootPermission.id get() = RootPermission
@ExperimentalPermission @ExperimentalPermission
override fun permissionId(id: String): PermissionId = PermissionId("console", id) override fun permissionId(id: String): PermissionId = PermissionId("console", id)

View File

@ -21,7 +21,7 @@ import net.mamoe.mirai.console.command.description.*
import net.mamoe.mirai.console.internal.command.AbstractReflectionCommand import net.mamoe.mirai.console.internal.command.AbstractReflectionCommand
import net.mamoe.mirai.console.internal.command.CompositeCommandSubCommandAnnotationResolver import net.mamoe.mirai.console.internal.command.CompositeCommandSubCommandAnnotationResolver
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.Permission
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
import kotlin.annotation.AnnotationRetention.RUNTIME import kotlin.annotation.AnnotationRetention.RUNTIME
@ -86,7 +86,7 @@ public abstract class CompositeCommand @OptIn(ExperimentalPermission::class) con
owner: CommandOwner, owner: CommandOwner,
vararg names: String, vararg names: String,
description: String = "no description available", description: String = "no description available",
parentPermission: PermissionId = owner.basePermission, parentPermission: Permission = owner.parentPermission,
prefixOptional: Boolean = false, prefixOptional: Boolean = false,
overrideContext: CommandArgumentContext = EmptyCommandArgumentContext overrideContext: CommandArgumentContext = EmptyCommandArgumentContext
) : Command, AbstractReflectionCommand(owner, names, description, parentPermission, prefixOptional), ) : Command, AbstractReflectionCommand(owner, names, description, parentPermission, prefixOptional),
@ -110,12 +110,6 @@ public abstract class CompositeCommand @OptIn(ExperimentalPermission::class) con
@Target(FUNCTION) @Target(FUNCTION)
protected annotation class SubCommand(vararg val value: String) protected annotation class SubCommand(vararg val value: String)
/** 指定子指令要求的权限 */
@Retention(RUNTIME)
@Target(FUNCTION)
@ExperimentalPermission
protected annotation class Permission(val value: String)
/** 指令描述 */ /** 指令描述 */
@Retention(RUNTIME) @Retention(RUNTIME)
@Target(FUNCTION) @Target(FUNCTION)

View File

@ -17,7 +17,6 @@ import net.mamoe.mirai.console.command.java.JRawCommand
import net.mamoe.mirai.console.internal.command.createOrFindCommandPermission import net.mamoe.mirai.console.internal.command.createOrFindCommandPermission
import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.ExperimentalPermission
import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.console.permission.Permission
import net.mamoe.mirai.console.permission.PermissionId
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
/** /**
@ -44,7 +43,7 @@ public abstract class RawCommand @OptIn(ExperimentalPermission::class) construct
/** 指令描述, 用于显示在 [BuiltInCommands.Help] */ /** 指令描述, 用于显示在 [BuiltInCommands.Help] */
public override val description: String = "<no descriptions given>", public override val description: String = "<no descriptions given>",
/** 指令父权限 */ /** 指令父权限 */
parentPermission: PermissionId = owner.basePermission, parentPermission: Permission = owner.parentPermission,
/** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */ /** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */
public override val prefixOptional: Boolean = false public override val prefixOptional: Boolean = false
) : Command { ) : Command {

View File

@ -23,7 +23,7 @@ import net.mamoe.mirai.console.command.java.JSimpleCommand
import net.mamoe.mirai.console.internal.command.AbstractReflectionCommand import net.mamoe.mirai.console.internal.command.AbstractReflectionCommand
import net.mamoe.mirai.console.internal.command.SimpleCommandSubCommandAnnotationResolver import net.mamoe.mirai.console.internal.command.SimpleCommandSubCommandAnnotationResolver
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.Permission
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
/** /**
@ -53,10 +53,10 @@ public abstract class SimpleCommand @OptIn(ExperimentalPermission::class) constr
owner: CommandOwner, owner: CommandOwner,
vararg names: String, vararg names: String,
description: String = "no description available", description: String = "no description available",
basePermission: PermissionId = owner.basePermission, parentPermission: Permission = owner.parentPermission,
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

@ -81,6 +81,21 @@ public interface CommandArgumentParser<out T : Any> {
public fun parse(raw: MessageContent, sender: CommandSender): T = parse(raw.content, sender) public fun parse(raw: MessageContent, sender: CommandSender): T = parse(raw.content, sender)
} }
/**
* 使用原 [this] 解析, 成功后使用 [mapper] 映射为另一个类型.
*/
public fun <T : Any, R : Any> CommandArgumentParser<T>.map(
mapper: CommandArgumentParser<R>.(T) -> R
): CommandArgumentParser<R> = MappingCommandArgumentParser(this, mapper)
private class MappingCommandArgumentParser<T : Any, R : Any>(
private val original: CommandArgumentParser<T>,
private val mapper: CommandArgumentParser<R>.(T) -> R
) : CommandArgumentParser<R> {
override fun parse(raw: String, sender: CommandSender): R = mapper(original.parse(raw, sender))
override fun parse(raw: MessageContent, sender: CommandSender): R = mapper(original.parse(raw, sender))
}
/** /**
* 解析一个字符串或 [SingleMessage] [T] 类型参数 * 解析一个字符串或 [SingleMessage] [T] 类型参数
* *

View File

@ -15,7 +15,7 @@ import net.mamoe.mirai.console.command.CommandOwner
import net.mamoe.mirai.console.command.CompositeCommand import net.mamoe.mirai.console.command.CompositeCommand
import net.mamoe.mirai.console.command.description.buildCommandArgumentContext import net.mamoe.mirai.console.command.description.buildCommandArgumentContext
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.Permission
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
/** /**
@ -73,14 +73,14 @@ public abstract class JCompositeCommand @OptIn(ExperimentalPermission::class)
@JvmOverloads constructor( @JvmOverloads constructor(
owner: CommandOwner, owner: CommandOwner,
vararg names: String, vararg names: String,
parentPermission: PermissionId = owner.basePermission, parentPermission: Permission = owner.parentPermission,
) : CompositeCommand(owner, *names, parentPermission = parentPermission) { ) : 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
@OptIn(ExperimentalPermission::class) @OptIn(ExperimentalPermission::class)
public final override var permission: net.mamoe.mirai.console.permission.Permission = super.permission public final override var permission: Permission = super.permission
protected set protected set
/** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */ /** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */

View File

@ -16,7 +16,6 @@ import net.mamoe.mirai.console.command.CommandManager.INSTANCE.execute
import net.mamoe.mirai.console.internal.command.createOrFindCommandPermission import net.mamoe.mirai.console.internal.command.createOrFindCommandPermission
import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.ExperimentalPermission
import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.console.permission.Permission
import net.mamoe.mirai.console.permission.PermissionId
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.SingleMessage import net.mamoe.mirai.message.data.SingleMessage
@ -55,7 +54,7 @@ public abstract class JRawCommand @OptIn(ExperimentalPermission::class)
public override val owner: CommandOwner, public override val owner: CommandOwner,
/** 指令名. 需要至少有一个元素. 所有元素都不能带有空格 */ /** 指令名. 需要至少有一个元素. 所有元素都不能带有空格 */
public override vararg val names: String, public override vararg val names: String,
parentPermission: PermissionId = owner.basePermission, parentPermission: Permission = owner.parentPermission,
) : Command { ) : Command {
/** 用法说明, 用于发送给用户 */ /** 用法说明, 用于发送给用户 */
public override var usage: String = "<no usages given>" public override var usage: String = "<no usages given>"

View File

@ -16,7 +16,6 @@ import net.mamoe.mirai.console.command.SimpleCommand
import net.mamoe.mirai.console.command.description.CommandArgumentContext import net.mamoe.mirai.console.command.description.CommandArgumentContext
import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.ExperimentalPermission
import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.console.permission.Permission
import net.mamoe.mirai.console.permission.PermissionId
/** /**
* Java 实现: * Java 实现:
@ -44,8 +43,8 @@ import net.mamoe.mirai.console.permission.PermissionId
public abstract class JSimpleCommand @OptIn(ExperimentalPermission::class) constructor( public abstract class JSimpleCommand @OptIn(ExperimentalPermission::class) constructor(
owner: CommandOwner, owner: CommandOwner,
vararg names: String, vararg names: String,
basePermission: PermissionId, basePermission: Permission,
) : SimpleCommand(owner, *names, basePermission = basePermission) { ) : SimpleCommand(owner, *names, parentPermission = basePermission) {
public override var description: String = super.description public override var description: String = super.description
protected set protected set

View File

@ -18,8 +18,6 @@ import net.mamoe.mirai.console.command.description.CommandArgumentContextAware
import net.mamoe.mirai.console.internal.data.kClassQualifiedNameOrTip import net.mamoe.mirai.console.internal.data.kClassQualifiedNameOrTip
import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.ExperimentalPermission
import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.console.permission.Permission
import net.mamoe.mirai.console.permission.PermissionId
import net.mamoe.mirai.console.permission.PermissionService
import net.mamoe.mirai.console.permission.PermissionService.Companion.testPermission import net.mamoe.mirai.console.permission.PermissionService.Companion.testPermission
import net.mamoe.mirai.message.data.* import net.mamoe.mirai.message.data.*
import kotlin.reflect.KAnnotatedElement import kotlin.reflect.KAnnotatedElement
@ -53,7 +51,7 @@ internal abstract class AbstractReflectionCommand @OptIn(ExperimentalPermission:
owner: CommandOwner, owner: CommandOwner,
names: Array<out String>, names: Array<out String>,
description: String = "<no description available>", description: String = "<no description available>",
parentPermission: PermissionId = owner.basePermission, parentPermission: Permission = owner.parentPermission,
prefixOptional: Boolean = false prefixOptional: Boolean = false
) : Command, AbstractCommand( ) : Command, AbstractCommand(
owner, owner,
@ -144,7 +142,7 @@ internal abstract class AbstractReflectionCommand @OptIn(ExperimentalPermission:
argsWithSubCommandNameNotRemoved: MessageChain, argsWithSubCommandNameNotRemoved: MessageChain,
removeSubName: Boolean removeSubName: Boolean
) { ) {
val args = parseArgs(sender, argsWithSubCommandNameNotRemoved, if (removeSubName) names.size else 0) val args = parseArgs(sender, argsWithSubCommandNameNotRemoved, if (removeSubName) 1 else 0)
if (!this.permission.testPermission(sender)) { if (!this.permission.testPermission(sender)) {
sender.sendMessage(usage) // TODO: 2020/8/26 #127 sender.sendMessage(usage) // TODO: 2020/8/26 #127
return return
@ -259,7 +257,7 @@ internal fun AbstractReflectionCommand.createSubCommand(
context: CommandArgumentContext context: CommandArgumentContext
): AbstractReflectionCommand.SubCommandDescriptor { ): AbstractReflectionCommand.SubCommandDescriptor {
val notStatic = !function.hasAnnotation<JvmStatic>() val notStatic = !function.hasAnnotation<JvmStatic>()
val overridePermission = function.findAnnotation<CompositeCommand.Permission>()//optional //val overridePermission = null//function.findAnnotation<CompositeCommand.PermissionId>()//optional
val subDescription = val subDescription =
function.findAnnotation<CompositeCommand.Description>()?.value ?: "" function.findAnnotation<CompositeCommand.Description>()?.value ?: ""
@ -331,7 +329,7 @@ internal fun AbstractReflectionCommand.createSubCommand(
commandName, commandName,
params, params,
subDescription, // overridePermission?.value subDescription, // overridePermission?.value
overridePermission?.value?.let { PermissionService.INSTANCE[PermissionId.parseFromString(it)] } ?: permission, permission,//overridePermission?.value?.let { PermissionService.INSTANCE[PermissionId.parseFromString(it)] } ?: permission,
onCommand = { sender: CommandSender, args: Array<out Any> -> onCommand = { sender: CommandSender, args: Array<out Any> ->
val result = if (notStatic) { val result = if (notStatic) {
if (hasSenderParam) { if (hasSenderParam) {

View File

@ -13,7 +13,6 @@ import net.mamoe.mirai.console.command.*
import net.mamoe.mirai.console.command.Command.Companion.primaryName import net.mamoe.mirai.console.command.Command.Companion.primaryName
import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.ExperimentalPermission
import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.console.permission.Permission
import net.mamoe.mirai.console.permission.PermissionId
import net.mamoe.mirai.console.permission.PermissionService import net.mamoe.mirai.console.permission.PermissionService
import net.mamoe.mirai.console.permission.PermissionService.Companion.testPermission import net.mamoe.mirai.console.permission.PermissionService.Companion.testPermission
import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Group
@ -143,7 +142,7 @@ internal fun Group.fuzzySearchMember(
} }
@OptIn(ExperimentalPermission::class) @OptIn(ExperimentalPermission::class)
internal fun Command.createOrFindCommandPermission(parent: PermissionId): Permission { internal fun Command.createOrFindCommandPermission(parent: Permission): Permission {
val id = owner.permissionId(primaryName) val id = owner.permissionId(primaryName)
return PermissionService.INSTANCE[id] ?: PermissionService.INSTANCE.register(id, description, parent) return PermissionService.INSTANCE[id] ?: PermissionService.INSTANCE.register(id, description, parent)
} }

View File

@ -16,6 +16,7 @@ import net.mamoe.mirai.console.MiraiConsole
import net.mamoe.mirai.console.data.runCatchingLog 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.Permission
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.PermissionService
import net.mamoe.mirai.console.permission.PermissionService.Companion.allocatePermissionIdForPlugin import net.mamoe.mirai.console.permission.PermissionService.Companion.allocatePermissionIdForPlugin
@ -44,11 +45,11 @@ internal abstract class JvmPluginInternal(
) : JvmPlugin, CoroutineScope { ) : JvmPlugin, CoroutineScope {
@OptIn(ExperimentalPermission::class) @OptIn(ExperimentalPermission::class)
final override val basePermission: PermissionId by lazy { final override val parentPermission: Permission by lazy {
PermissionService.INSTANCE.register( PermissionService.INSTANCE.register(
PermissionService.INSTANCE.allocatePermissionIdForPlugin(name, "*"), PermissionService.INSTANCE.allocatePermissionIdForPlugin(name, "*"),
"The base permission" "The base permission"
).id )
} }
final override var isEnabled: Boolean = false final override var isEnabled: Boolean = false
@ -110,7 +111,7 @@ internal abstract class JvmPluginInternal(
} }
internal fun internalOnEnable(): Boolean { internal fun internalOnEnable(): Boolean {
basePermission parentPermission
if (!firstRun) refreshCoroutineContext() if (!firstRun) refreshCoroutineContext()
kotlin.runCatching { kotlin.runCatching {
onEnable() onEnable()

View File

@ -23,14 +23,14 @@ 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 = RootPermission.id parent: Permission
): 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, parent: Permission): 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, parent)
val old = permissions.putIfAbsent(id, instance) val old = permissions.putIfAbsent(id, instance)
if (old != null) throw DuplicatedPermissionRegistrationException(instance, old) if (old != null) throw DuplicatedPermissionRegistrationException(instance, old)
return instance return instance

View File

@ -9,28 +9,27 @@
package net.mamoe.mirai.console.permission package net.mamoe.mirai.console.permission
import kotlinx.serialization.Serializable
import net.mamoe.mirai.console.data.AutoSavePluginConfig import net.mamoe.mirai.console.data.AutoSavePluginConfig
import net.mamoe.mirai.console.data.PluginDataExtensions.withDefault import net.mamoe.mirai.console.data.PluginDataExtensions.withDefault
import net.mamoe.mirai.console.data.value import net.mamoe.mirai.console.data.value
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.CopyOnWriteArrayList
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.KType
import kotlin.reflect.full.createType
@ExperimentalPermission @ExperimentalPermission
public object AllGrantPermissionService : PermissionService<PermissionImpl> { internal object AllGrantPermissionService : PermissionService<PermissionImpl> {
private val all = ConcurrentHashMap<PermissionId, PermissionImpl>() private val all = ConcurrentHashMap<PermissionId, PermissionImpl>()
override val permissionType: KClass<PermissionImpl> override val permissionType: KClass<PermissionImpl> get() = PermissionImpl::class
get() = PermissionImpl::class override val rootPermission: PermissionImpl get() = RootPermissionImpl
override fun register( override fun register(
id: PermissionId, id: PermissionId,
description: String, description: String,
base: PermissionId parent: Permission
): PermissionImpl { ): PermissionImpl {
val new = PermissionImpl(id, description, base) val new = PermissionImpl(id, description, parent)
val old = all.putIfAbsent(id, new) val old = all.putIfAbsent(id, new)
if (old != null) throw DuplicatedPermissionRegistrationException(new, old) if (old != null) throw DuplicatedPermissionRegistrationException(new, old)
return new return new
@ -51,18 +50,23 @@ public object AllGrantPermissionService : PermissionService<PermissionImpl> {
} }
} }
@Suppress("DEPRECATION")
@OptIn(ExperimentalPermission::class)
private val RootPermissionImpl = PermissionImpl(PermissionId("*", "*"), "The root permission").also { it.parent = it }
@ExperimentalPermission @ExperimentalPermission
public object AllDenyPermissionService : PermissionService<PermissionImpl> { internal object AllDenyPermissionService : PermissionService<PermissionImpl> {
private val all = ConcurrentHashMap<PermissionId, PermissionImpl>() private val all = ConcurrentHashMap<PermissionId, PermissionImpl>()
override val permissionType: KClass<PermissionImpl> override val permissionType: KClass<PermissionImpl>
get() = PermissionImpl::class get() = PermissionImpl::class
override val rootPermission: PermissionImpl get() = RootPermissionImpl
override fun register( override fun register(
id: PermissionId, id: PermissionId,
description: String, description: String,
base: PermissionId parent: Permission
): PermissionImpl { ): PermissionImpl {
val new = PermissionImpl(id, description, base) val new = PermissionImpl(id, description, parent)
val old = all.putIfAbsent(id, new) val old = all.putIfAbsent(id, new)
if (old != null) throw DuplicatedPermissionRegistrationException(new, old) if (old != null) throw DuplicatedPermissionRegistrationException(new, old)
return new return new
@ -91,27 +95,23 @@ internal object BuiltInPermissionService : AbstractConcurrentPermissionService<P
override val permissionType: KClass<PermissionImpl> override val permissionType: KClass<PermissionImpl>
get() = PermissionImpl::class get() = PermissionImpl::class
override val permissions: MutableMap<PermissionId, PermissionImpl> = ConcurrentHashMap() override val permissions: MutableMap<PermissionId, PermissionImpl> = ConcurrentHashMap()
override val rootPermission: PermissionImpl
get() = RootPermissionImpl
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
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, parent: Permission): PermissionImpl =
PermissionImpl(id, description, base) PermissionImpl(id, description, parent)
internal val config: ConcurrentSaveData<PermissionImpl> = internal val config: ConcurrentSaveData =
ConcurrentSaveData( ConcurrentSaveData("PermissionService")
PermissionImpl::class.createType(),
"PermissionService",
)
@Suppress("RedundantVisibilityModifier") @Suppress("RedundantVisibilityModifier")
@ExperimentalPermission @ExperimentalPermission
internal class ConcurrentSaveData<P : Permission> private constructor( internal class ConcurrentSaveData private constructor(
permissionType: KType,
public override val saveName: String, public override val saveName: String,
// delegate: PluginConfig,
@Suppress("UNUSED_PARAMETER") primaryConstructorMark: Any? @Suppress("UNUSED_PARAMETER") primaryConstructorMark: Any?
) : AutoSavePluginConfig() { ) : AutoSavePluginConfig() {
public val grantedPermissionMap: MutableMap<PermissionId, MutableList<AbstractPermissibleIdentifier>> public val grantedPermissionMap: MutableMap<PermissionId, MutableList<AbstractPermissibleIdentifier>>
@ -120,11 +120,49 @@ internal object BuiltInPermissionService : AbstractConcurrentPermissionService<P
public companion object { public companion object {
@JvmStatic @JvmStatic
public operator fun <P : Permission> invoke( public operator fun invoke(
permissionType: KType,
saveName: String, saveName: String,
// delegate: PluginConfig, // delegate: PluginConfig,
): ConcurrentSaveData<P> = ConcurrentSaveData(permissionType, saveName, null) ): ConcurrentSaveData = ConcurrentSaveData(saveName, null)
} }
} }
} }
/**
* [Permission] 的简单实现
*/
@Serializable
@ExperimentalPermission
internal data class PermissionImpl @Deprecated("Only for Root") constructor(
override val id: PermissionId,
override val description: String,
) : Permission {
override lateinit var parent: Permission
@Suppress("DEPRECATION")
constructor(id: PermissionId, description: String, parent: Permission) : this(id, description) {
this.parent = parent
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as PermissionImpl
if (id != other.id) return false
if (description != other.description) return false
if (parent != other.parent) return false
return true
}
override fun hashCode(): Int {
var result = id.hashCode()
result = 31 * result + description.hashCode()
result = 31 * result + parent.hashCode()
return result
}
override fun toString(): String = "PermissionImpl(id=$id, description='$description', parentId=$parent)"
}

View File

@ -9,8 +9,6 @@
package net.mamoe.mirai.console.permission package net.mamoe.mirai.console.permission
import kotlinx.serialization.Serializable
import net.mamoe.mirai.console.permission.PermissionService.Companion.findCorrespondingPermission
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
@ -25,22 +23,29 @@ import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
public interface Permission { public interface Permission {
public val id: PermissionId public val id: PermissionId
public val description: String public val description: String
public val parentId: PermissionId
}
@OptIn(ExperimentalPermission::class) /**
private val ROOT_PERMISSION_ID = PermissionId("*", "*") * [RootPermission] parent 为自身
*/
public val parent: Permission
}
/** /**
* 所有权限的父权限. * 所有权限的父权限.
*/ */
@get:JvmName("getRootPermission") @get:JvmName("getRootPermission")
@ExperimentalPermission @ExperimentalPermission
public val RootPermission: Permission by lazy { public val RootPermission: Permission
get() = PermissionService.INSTANCE.rootPermission
/**
* 所有内建指令的权限
*/
@ExperimentalPermission
public val RootConsoleBuiltInPermission: Permission by lazy {
PermissionService.INSTANCE.register( PermissionService.INSTANCE.register(
ROOT_PERMISSION_ID, PermissionId("console", "*"),
"The parent of any permission", "The parent of any built-in commands"
ROOT_PERMISSION_ID
) )
} }
@ -48,16 +53,5 @@ public val RootPermission: Permission by lazy {
@ExperimentalPermission @ExperimentalPermission
public fun Permission.parentsWithSelfSequence(): Sequence<Permission> = public fun Permission.parentsWithSelfSequence(): Sequence<Permission> =
generateSequence(this) { p -> generateSequence(this) { p ->
p.parentId.findCorrespondingPermission()?.takeIf { parent -> parent != p } p.parent.takeIf { parent -> parent != p }
} }
/**
* [Permission] 的简单实现
*/
@Serializable
@ExperimentalPermission
public data class PermissionImpl(
override val id: PermissionId,
override val description: String,
override val parentId: PermissionId = RootPermission.id
) : Permission

View File

@ -23,6 +23,7 @@ import kotlin.reflect.full.isSuperclassOf
public interface PermissionService<P : Permission> { public interface PermissionService<P : Permission> {
@ExperimentalPermission @ExperimentalPermission
public val permissionType: KClass<P> public val permissionType: KClass<P>
public val rootPermission: P
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -46,7 +47,7 @@ public interface PermissionService<P : Permission> {
public fun register( public fun register(
id: PermissionId, id: PermissionId,
description: String, description: String,
base: PermissionId = RootPermission.id parent: Permission = RootPermission
): P ): P
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////

View File

@ -35,7 +35,7 @@ internal fun startupConsoleThread() {
val next = MiraiConsole.requestInput("").let { val next = MiraiConsole.requestInput("").let {
when { when {
it.startsWith(CommandManager.commandPrefix) -> it it.startsWith(CommandManager.commandPrefix) -> it
it == "?" -> CommandManager.commandPrefix + BuiltInCommands.Help.primaryName it == "?" -> CommandManager.commandPrefix + BuiltInCommands.HelpCommand.primaryName
else -> CommandManager.commandPrefix + it else -> CommandManager.commandPrefix + it
} }
} }