mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-25 15:40:28 +08:00
PermissionService fundamental
This commit is contained in:
parent
77176f5242
commit
78d5f56c49
@ -32,6 +32,8 @@ import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
|
||||
import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip
|
||||
import net.mamoe.mirai.console.internal.data.castOrNull
|
||||
import net.mamoe.mirai.console.internal.plugin.rootCauseOrSelf
|
||||
import net.mamoe.mirai.console.permission.ExperimentalPermission
|
||||
import net.mamoe.mirai.console.permission.Permissible
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScope
|
||||
import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScopeContext
|
||||
@ -132,7 +134,8 @@ import kotlin.internal.LowPriorityInOverloadResolution
|
||||
* @see toCommandSender
|
||||
* @see asCommandSender
|
||||
*/
|
||||
public interface CommandSender : CoroutineScope {
|
||||
@OptIn(ExperimentalPermission::class)
|
||||
public interface CommandSender : CoroutineScope, Permissible {
|
||||
/**
|
||||
* 与这个 [CommandSender] 相关的 [Bot].
|
||||
* 当通过控制台执行时为 `null`.
|
||||
@ -158,6 +161,10 @@ public interface CommandSender : CoroutineScope {
|
||||
*/
|
||||
public val name: String
|
||||
|
||||
@ExperimentalPermission
|
||||
override val identifier: String
|
||||
get() = user?.id?.toString() ?: bot?.id?.toString() ?: error("Internal error: bot user and bot are null")
|
||||
|
||||
/**
|
||||
* 立刻发送一条消息.
|
||||
*
|
||||
|
@ -2,11 +2,13 @@ package net.mamoe.mirai.console.extensions
|
||||
|
||||
import net.mamoe.mirai.console.extension.AbstractExtensionPoint
|
||||
import net.mamoe.mirai.console.extension.SingletonExtension
|
||||
import net.mamoe.mirai.console.permission.ExperimentalPermission
|
||||
import net.mamoe.mirai.console.permission.PermissionService
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
|
||||
@ExperimentalPermission
|
||||
@ConsoleExperimentalAPI
|
||||
public interface PermissionServiceProvider : SingletonExtension<PermissionService> {
|
||||
public interface PermissionServiceProvider : SingletonExtension<PermissionService<*>> {
|
||||
public companion object ExtensionPoint :
|
||||
AbstractExtensionPoint<PermissionServiceProvider>(PermissionServiceProvider::class)
|
||||
}
|
@ -16,7 +16,7 @@ import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.data.runCatchingLog
|
||||
import net.mamoe.mirai.console.internal.data.mkdir
|
||||
import net.mamoe.mirai.console.permission.ExperimentalPermission
|
||||
import net.mamoe.mirai.console.permission.Identifier
|
||||
import net.mamoe.mirai.console.permission.PermissionIdentifier
|
||||
import net.mamoe.mirai.console.plugin.Plugin
|
||||
import net.mamoe.mirai.console.plugin.PluginManager
|
||||
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.safeLoader
|
||||
@ -47,8 +47,8 @@ internal abstract class JvmPluginInternal(
|
||||
resourceContainerDelegate.getResourceAsStream(path)
|
||||
|
||||
@OptIn(ExperimentalPermission::class)
|
||||
override fun allocate(identifierString: String): Identifier {
|
||||
return Identifier(description.name)
|
||||
override fun permissionIdentifier(identifierString: String): PermissionIdentifier {
|
||||
return PermissionIdentifier(description.name, identifierString)
|
||||
}
|
||||
|
||||
// region JvmPlugin
|
||||
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.permission
|
||||
|
||||
import kotlin.annotation.AnnotationTarget.*
|
||||
|
||||
/**
|
||||
* 标记一个实验性的权限系统 API
|
||||
*/
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
|
||||
@Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR)
|
||||
@MustBeDocumented
|
||||
public annotation class ExperimentalPermission(
|
||||
val message: String = ""
|
||||
)
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("NOTHING_TO_INLINE", "unused")
|
||||
|
||||
package net.mamoe.mirai.console.permission
|
||||
|
||||
@ExperimentalPermission
|
||||
public interface Permissible {
|
||||
public val identifier: String
|
||||
}
|
||||
|
||||
@ExperimentalPermission
|
||||
public inline fun Permissible.hasPermission(permission: Permission): Boolean =
|
||||
PermissionService.run { permission.testPermission(this@hasPermission) }
|
||||
|
||||
@ExperimentalPermission
|
||||
public inline fun Permissible.hasPermission(permission: PermissionIdentifier): Boolean =
|
||||
PermissionService.run { permission.testPermission(this@hasPermission) }
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.permission
|
||||
|
||||
|
||||
/**
|
||||
* 一个权限节点
|
||||
*/
|
||||
@ExperimentalPermission
|
||||
public interface Permission {
|
||||
public val identifier: PermissionIdentifier
|
||||
public val description: String
|
||||
public val base: PermissionIdentifier?
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("unused")
|
||||
|
||||
package net.mamoe.mirai.console.permission
|
||||
|
||||
import net.mamoe.mirai.console.command.CommandSender
|
||||
|
||||
@ExperimentalPermission
|
||||
public fun interface PermissionChecker {
|
||||
public fun CommandSender.testPermission(): Boolean
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.permission
|
||||
|
||||
import net.mamoe.mirai.console.command.CommandSender
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
@ExperimentalPermission
|
||||
public abstract class PermissionGroup(
|
||||
private val identifierNamespace: PermissionIdentifierNamespace,
|
||||
) {
|
||||
@ExperimentalPermission
|
||||
public inner class PermissionBuilder {
|
||||
@JvmField
|
||||
internal var description: String = "<no description given>"
|
||||
|
||||
@JvmField
|
||||
internal var basePermission: PermissionIdentifier? = null
|
||||
|
||||
@JvmField
|
||||
internal var permissionChecker: PermissionChecker? = null
|
||||
|
||||
public fun description(description: String): PermissionBuilder = apply { this.description = description }
|
||||
public fun dependsOn(basePermission: PermissionIdentifier?): PermissionBuilder =
|
||||
apply { this.basePermission = basePermission }
|
||||
|
||||
public fun dependsOn(basePermission: Permission?): PermissionBuilder =
|
||||
apply { this.basePermission = basePermission?.identifier }
|
||||
|
||||
public fun basePermission(basePermission: PermissionIdentifier?): PermissionBuilder =
|
||||
apply { this.basePermission = basePermission }
|
||||
|
||||
public fun basePermission(basePermission: Permission?): PermissionBuilder =
|
||||
apply { this.basePermission = basePermission?.identifier }
|
||||
|
||||
public fun defaults(permissionChecker: PermissionChecker?): PermissionBuilder =
|
||||
apply { this.permissionChecker = permissionChecker }
|
||||
|
||||
public fun build(property: KProperty<*>): Permission {
|
||||
return PermissionService.register(
|
||||
identifierNamespace.permissionIdentifier(property.name),
|
||||
description,
|
||||
basePermission
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public infix fun String.dependsOn(permission: Permission): PermissionBuilder {
|
||||
return PermissionBuilder().apply { description(this@dependsOn);dependsOn(permission) }
|
||||
}
|
||||
|
||||
|
||||
public infix fun PermissionBuilder.defaults(permission: PermissionChecker): PermissionBuilder {
|
||||
return apply { defaults(permission) }
|
||||
}
|
||||
|
||||
public infix fun PermissionBuilder.defaults(permission: CommandSender.() -> Boolean): PermissionBuilder {
|
||||
return apply { defaults(permission) }
|
||||
}
|
||||
|
||||
public infix fun String.defaults(permission: PermissionChecker): PermissionBuilder {
|
||||
return PermissionBuilder().apply { defaults(permission) }
|
||||
}
|
||||
|
||||
|
||||
public operator fun String.invoke(block: PermissionBuilder.() -> Unit): PermissionBuilder {
|
||||
return PermissionBuilder().apply(block)
|
||||
}
|
||||
|
||||
public operator fun String.provideDelegate(thisRef: PermissionGroup, property: KProperty<*>): Permission =
|
||||
PermissionBuilder().apply { description(this@provideDelegate) }.build(property)
|
||||
|
||||
public operator fun Permission.getValue(thisRef: PermissionGroup, property: KProperty<*>): Permission = this
|
||||
public operator fun PermissionBuilder.getValue(thisRef: PermissionGroup, property: KProperty<*>): Permission =
|
||||
this.build(property)
|
||||
}
|
||||
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.permission
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@Serializable
|
||||
@ExperimentalPermission
|
||||
public data class PermissionIdentifier(
|
||||
public val namespace: String,
|
||||
public val id: String
|
||||
)
|
||||
|
||||
@ExperimentalPermission
|
||||
public interface PermissionIdentifierNamespace {
|
||||
@ExperimentalPermission
|
||||
public fun permissionIdentifier(identifierString: String): PermissionIdentifier
|
||||
}
|
@ -7,28 +7,122 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("NOTHING_TO_INLINE", "unused")
|
||||
|
||||
package net.mamoe.mirai.console.permission
|
||||
|
||||
import net.mamoe.mirai.console.extension.useExtensions
|
||||
import net.mamoe.mirai.console.data.AutoSavePluginConfig
|
||||
import net.mamoe.mirai.console.data.Value
|
||||
import net.mamoe.mirai.console.data.value
|
||||
import net.mamoe.mirai.console.extensions.PermissionServiceProvider
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
|
||||
/**
|
||||
* [PermissionServiceProvider]
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
public interface PermissionService {
|
||||
@ExperimentalPermission
|
||||
public interface PermissionService<P : Permission> {
|
||||
public fun register(
|
||||
identifier: PermissionIdentifier,
|
||||
description: String,
|
||||
base: PermissionIdentifier? = null
|
||||
): P
|
||||
|
||||
public operator fun get(identifier: PermissionIdentifier): P?
|
||||
|
||||
|
||||
public companion object : PermissionService {
|
||||
public fun getGrantedPermissions(permissible: Permissible): List<PermissionIdentifier>
|
||||
|
||||
|
||||
public fun testPermission(permissible: Permissible, permission: P): Boolean =
|
||||
permissible.getGrantedPermissions().any { it == permission.identifier }
|
||||
|
||||
|
||||
public companion object INSTANCE : PermissionService<Permission> {
|
||||
private val builtIn: PermissionService<out Permission> get() = TODO("PS IMPL")
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private val instance by lazy {
|
||||
PermissionServiceProvider.useExtensions { }
|
||||
PermissionServiceProvider.getExtensions().singleOrNull()?.extension?.instance
|
||||
?: builtIn // TODO: 2020/9/4 ask for further choice
|
||||
as PermissionService<Permission>
|
||||
}
|
||||
|
||||
override fun register(
|
||||
identifier: PermissionIdentifier,
|
||||
description: String,
|
||||
base: PermissionIdentifier?
|
||||
): Permission = instance.register(identifier, description, base)
|
||||
|
||||
override fun get(identifier: PermissionIdentifier): Permission? = instance[identifier]
|
||||
override fun getGrantedPermissions(permissible: Permissible): List<PermissionIdentifier> =
|
||||
instance.getGrantedPermissions(permissible)
|
||||
}
|
||||
}
|
||||
|
||||
public interface proprietary
|
||||
@ExperimentalPermission
|
||||
public interface HotDeploymentSupportPermissionService<P : Permission> : PermissionService<P> {
|
||||
public fun grant(permissible: Permissible, permission: P)
|
||||
public fun deny(permissible: Permissible, permission: P)
|
||||
}
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
public interface Permission
|
||||
@ExperimentalPermission
|
||||
public open class HotDeploymentNotSupportedException : Exception {
|
||||
public constructor() : super()
|
||||
public constructor(message: String?) : super(message)
|
||||
public constructor(message: String?, cause: Throwable?) : super(message, cause)
|
||||
public constructor(cause: Throwable?) : super(cause)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* [PermissionServiceProvider]
|
||||
*/
|
||||
@ExperimentalPermission
|
||||
public abstract class AbstractPermissionService<P : Permission> : AutoSavePluginConfig(), PermissionService<P> {
|
||||
@JvmField
|
||||
protected val permissions: ConcurrentLinkedQueue<P> = ConcurrentLinkedQueue()
|
||||
|
||||
@JvmField
|
||||
protected val grantedPermissionMap: Value<MutableMap<String, MutableList<PermissionIdentifier>>> = value()
|
||||
|
||||
public override fun getGrantedPermissions(permissible: Permissible): List<PermissionIdentifier> =
|
||||
grantedPermissionMap.value[permissible.identifier].orEmpty()
|
||||
|
||||
public override operator fun get(identifier: PermissionIdentifier): P? =
|
||||
permissions.find { it.identifier == identifier }
|
||||
|
||||
public override fun testPermission(permissible: Permissible, permission: P): Boolean =
|
||||
permissible.getGrantedPermissions().any { it == permission.identifier }
|
||||
}
|
||||
|
||||
@ExperimentalPermission
|
||||
public inline fun Permissible.getGrantedPermissions(): List<PermissionIdentifier> =
|
||||
PermissionService.run { this.getGrantedPermissions(this@getGrantedPermissions) }
|
||||
|
||||
@ExperimentalPermission
|
||||
public inline fun Permission.testPermission(permissible: Permissible): Boolean =
|
||||
PermissionService.run { testPermission(permissible, this@testPermission) }
|
||||
|
||||
@ExperimentalPermission
|
||||
public inline fun PermissionIdentifier.testPermission(permissible: Permissible): Boolean {
|
||||
val p = PermissionService[this] ?: return false
|
||||
return p.testPermission(permissible)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalPermission::class)
|
||||
private class PermissionServiceImpl : AbstractPermissionService<PermissionServiceImpl.PermissionImpl>() {
|
||||
private val instances: ConcurrentLinkedQueue<PermissionImpl> = ConcurrentLinkedQueue()
|
||||
|
||||
private class PermissionImpl(
|
||||
override val identifier: PermissionIdentifier,
|
||||
override val description: String,
|
||||
override val base: PermissionIdentifier?
|
||||
) : Permission
|
||||
|
||||
override fun register(
|
||||
identifier: PermissionIdentifier,
|
||||
description: String,
|
||||
base: PermissionIdentifier?
|
||||
): PermissionImpl = PermissionImpl(identifier, description, base)
|
||||
}
|
@ -21,6 +21,8 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.mirai.console.data.AutoSavePluginDataHolder
|
||||
import net.mamoe.mirai.console.data.PluginConfig
|
||||
import net.mamoe.mirai.console.data.PluginData
|
||||
import net.mamoe.mirai.console.permission.ExperimentalPermission
|
||||
import net.mamoe.mirai.console.permission.PermissionIdentifierNamespace
|
||||
import net.mamoe.mirai.console.plugin.Plugin
|
||||
import net.mamoe.mirai.console.plugin.PluginFileExtensions
|
||||
import net.mamoe.mirai.console.plugin.ResourceContainer
|
||||
@ -41,8 +43,9 @@ import net.mamoe.mirai.utils.MiraiLogger
|
||||
* @see JvmPlugin 支持文件系统扩展
|
||||
* @see ResourceContainer 支持资源获取 (如 Jar 中的资源文件)
|
||||
*/
|
||||
@OptIn(ExperimentalPermission::class)
|
||||
public interface JvmPlugin : Plugin, CoroutineScope,
|
||||
PluginFileExtensions, ResourceContainer, AutoSavePluginDataHolder {
|
||||
PluginFileExtensions, ResourceContainer, AutoSavePluginDataHolder, PermissionIdentifierNamespace {
|
||||
|
||||
/** 日志 */
|
||||
public val logger: MiraiLogger
|
||||
|
Loading…
Reference in New Issue
Block a user