diff --git a/mirai-console/backend/mirai-console/src/command/BuiltInCommands.kt b/mirai-console/backend/mirai-console/src/command/BuiltInCommands.kt index b57af68d0..55ff3f0ff 100644 --- a/mirai-console/backend/mirai-console/src/command/BuiltInCommands.kt +++ b/mirai-console/backend/mirai-console/src/command/BuiltInCommands.kt @@ -38,7 +38,6 @@ import net.mamoe.mirai.console.internal.permission.BuiltInPermissionService import net.mamoe.mirai.console.internal.pluginManagerImpl import net.mamoe.mirai.console.internal.util.runIgnoreException import net.mamoe.mirai.console.permission.Permission -import net.mamoe.mirai.console.permission.Permission.Companion.parentsWithSelf import net.mamoe.mirai.console.permission.PermissionId import net.mamoe.mirai.console.permission.PermissionService import net.mamoe.mirai.console.permission.PermissionService.Companion.cancel @@ -222,6 +221,34 @@ public object BuiltInCommands { ), BuiltInCommandInternal { // TODO: 2020/9/10 improve Permission command + /* 用于解析权限继承关系 */ + private class PermTree( + val perm: Permission, + val sub: MutableList<PermissionId> = mutableListOf(), + var linked: Boolean = false, + var implicit: Boolean = false, + ) { + companion object { + fun sortView(view: PermTree) { + view.sub.sortWith { p1, p2 -> + val namespaceCompare = p1.namespace compareTo p2.namespace + if (namespaceCompare != 0) return@sortWith namespaceCompare + + if (p1.name == p2.name) return@sortWith 0 // ? + if (p1.name == "*") return@sortWith -1 + if (p2.name == "*") return@sortWith 1 + + return@sortWith p1.name compareTo p2.name + } + } + } + } + + private fun renderDepth(depth: Int, sb: AnsiMessageBuilder) { + repeat(depth) { sb.append(" | ") } + } + + @Description("授权一个权限") @SubCommand("permit", "grant", "add") public suspend fun CommandSender.permit( @@ -256,16 +283,64 @@ public object BuiltInCommands { @SubCommand("permittedPermissions", "pp", "grantedPermissions", "gp") public suspend fun CommandSender.permittedPermissions( @Name("被许可人 ID") target: PermitteeId, - @Name("包括重复") all: Boolean = false, + @Name("显示全部") all: Boolean = true, ) { - var grantedPermissions = target.getPermittedPermissions().toList() - if (!all) { - grantedPermissions = grantedPermissions.filter { thisPerm -> - grantedPermissions.none { other -> thisPerm.parentsWithSelf.drop(1).any { it == other } } - } - } + val grantedPermissions = target.getPermittedPermissions().toList() if (grantedPermissions.isEmpty()) { sendMessage("${target.asString()} 未被授予任何权限. 使用 `${CommandManager.commandPrefix}permission grant` 给予权限.") + } else if (all) { + val allPermissions = PermissionService.INSTANCE.getRegisteredPermissions().toList() + val permMapping = mutableMapOf<PermissionId, PermTree>() + grantedPermissions.forEach { granted -> + permMapping[granted.id] = PermTree(granted).also { it.implicit = false } + } + val root = PermissionService.INSTANCE.rootPermission + fun linkPmTree(permTree: PermTree) { + allPermissions.forEach { perm -> + if (perm.id == root.id) return@forEach + if (perm.parent.id == permTree.perm.id) { + permTree.sub.add(perm.id) + val subp = permMapping[perm.id] ?: kotlin.run { + val p = PermTree(perm) + p.implicit = true + permMapping[perm.id] = p + linkPmTree(p) + p + } + subp.linked = true + } + } + } + permMapping.values.toList().forEach { linkPmTree(it) } + permMapping.values.forEach { PermTree.sortView(it) } + + @Suppress("LocalVariableName") + val BG_BLACK = "\u001B[40m" + fun render(depth: Int, view: PermTree, sb: AnsiMessageBuilder) { + if (view.implicit) { + sb.gray() + sb.append(view.perm.id) + sb.append(" (implicit)\n") + sb.reset().white().ansi(BG_BLACK) + } else { + sb.append(view.perm.id) + sb.append('\n') + } + view.sub.forEach { sub -> + val subView = permMapping[sub] ?: error("Error in resolving $sub") + renderDepth(depth, sb) + sb.append(" |- ") + render(depth + 1, subView, sb) + } + } + sendAnsiMessage { + ansi(BG_BLACK).white() + permMapping.forEach { (pid, tree) -> + if (!tree.linked) { + render(0, tree, this) + } + } + } } else { sendMessage(grantedPermissions.joinToString("\n") { it.id.toString() }) } @@ -274,10 +349,6 @@ public object BuiltInCommands { @Description("查看所有权限列表") @SubCommand("listPermissions", "lp") public suspend fun CommandSender.listPermissions() { - class PermTree( - val perm: Permission, - val sub: MutableList<PermissionId> = mutableListOf(), - ) val rootView = PermTree(PermissionService.INSTANCE.rootPermission) val mappings = mutableMapOf<PermissionId, PermTree>() @@ -295,18 +366,7 @@ public object BuiltInCommands { parentView.sub.add(perm.id) } - mappings.values.forEach { view -> - view.sub.sortWith { p1, p2 -> - val namespaceCompare = p1.namespace compareTo p2.namespace - if (namespaceCompare != 0) return@sortWith namespaceCompare - - if (p1.name == p2.name) return@sortWith 0 // ? - if (p1.name == "*") return@sortWith -1 - if (p2.name == "*") return@sortWith 1 - - return@sortWith p1.name compareTo p2.name - } - } + mappings.values.forEach { PermTree.sortView(it) } //*:* // | `- @@ -317,10 +377,6 @@ public object BuiltInCommands { // | | |- val prefixed = 50 - fun renderDepth(depth: Int, sb: AnsiMessageBuilder) { - repeat(depth) { sb.append(" | ") } - } - fun render(depth: Int, view: PermTree, sb: AnsiMessageBuilder) { kotlin.run { // render perm id var doReset = false diff --git a/mirai-console/backend/mirai-console/src/util/AnsiMessageBuilder.kt b/mirai-console/backend/mirai-console/src/util/AnsiMessageBuilder.kt index ff1c36b5f..40430cc24 100644 --- a/mirai-console/backend/mirai-console/src/util/AnsiMessageBuilder.kt +++ b/mirai-console/backend/mirai-console/src/util/AnsiMessageBuilder.kt @@ -227,7 +227,7 @@ private val DROP_ANSI_PATTERN = """\u001b[\u0040–\u005F]""".toRegex() private object Color { const val RESET = "\u001b[0m" - const val WHITE = "\u001b[30m" + const val WHITE = "\u001b[97m" const val RED = "\u001b[31m" const val EMERALD_GREEN = "\u001b[32m" const val GOLD = "\u001b[33m"