From 485e7ec9f780b005d7e12541efd8c3c1e74cb9d0 Mon Sep 17 00:00:00 2001 From: Him188 Date: Tue, 8 Sep 2020 21:35:30 +0800 Subject: [PATCH] Rearrange implementations --- .../AbstractConcurrentPermissionService.kt | 58 +++++++++++++ .../permission/BuiltInPermissionServices.kt | 6 +- ...licatedPermissionRegistrationException.kt} | 13 +-- .../mirai/console/permission/Permissible.kt | 68 +-------------- .../permission/PermissibleIdentifier.kt | 57 +++++++++++++ .../console/permission/PermissionGroup.kt | 84 ------------------- .../mirai/console/permission/PermissionId.kt | 5 -- ...ionChecker.kt => PermissionIdNamespace.kt} | 9 +- .../console/permission/PermissionService.kt | 59 +++---------- 9 files changed, 136 insertions(+), 223 deletions(-) create mode 100644 backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/AbstractConcurrentPermissionService.kt rename backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/{Exceptions.kt => DuplicatedPermissionRegistrationException.kt} (63%) create mode 100644 backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissibleIdentifier.kt delete mode 100644 backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionGroup.kt rename backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/{PermissionChecker.kt => PermissionIdNamespace.kt} (71%) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/AbstractConcurrentPermissionService.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/AbstractConcurrentPermissionService.kt new file mode 100644 index 000000000..2abe901de --- /dev/null +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/AbstractConcurrentPermissionService.kt @@ -0,0 +1,58 @@ +/* + * 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.permission.PermissibleIdentifier.Companion.grantedWith +import java.util.concurrent.CopyOnWriteArrayList + +@ExperimentalPermission +public abstract class AbstractConcurrentPermissionService

: PermissionService

{ + protected abstract val permissions: MutableMap + protected abstract val grantedPermissionsMap: MutableMap> + + protected abstract fun createPermission( + id: PermissionId, + description: String, + base: PermissionId? + ): P + + override fun get(id: PermissionId): P? = permissions[id] + + override fun register(id: PermissionId, description: String, base: PermissionId?): P { + grantedPermissionsMap[id] = CopyOnWriteArrayList() // mutations are not quite often performed + val instance = createPermission(id, description, base) + if (permissions.putIfAbsent(id, instance) != null) { + throw DuplicatedPermissionRegistrationException("Duplicated Permission registry. new: $instance, old: ${permissions[id]}") + } + return instance + } + + override fun grant(permissibleIdentifier: PermissibleIdentifier, permission: P) { + val id = permission.id + grantedPermissionsMap[id]?.add(permissibleIdentifier) + ?: error("Bad PermissionService implementation: grantedPermissionsMap[id] is null.") + } + + override fun deny(permissibleIdentifier: PermissibleIdentifier, permission: P) { + grantedPermissionsMap[permission.id]?.remove(permissibleIdentifier) + } + + public override fun getGrantedPermissions(permissible: Permissible): Sequence

= sequence

{ + for ((permissionIdentifier, permissibleIdentifiers) in grantedPermissionsMap) { + val myIdentifier = permissible.identifier + + val granted = + if (permissibleIdentifiers.isEmpty()) false + else permissibleIdentifiers.any { myIdentifier grantedWith it } + + if (granted) get(permissionIdentifier)?.let { yield(it) } + } + } +} \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/BuiltInPermissionServices.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/BuiltInPermissionServices.kt index 368b08cb8..bb84dc27a 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/BuiltInPermissionServices.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/BuiltInPermissionServices.kt @@ -36,7 +36,7 @@ public object AllGrantPermissionService : PermissionService { ): PermissionImpl { val new = PermissionImpl(id, description, base) if (all.putIfAbsent(id, new) != null) { - throw DuplicatedRegistrationException("Duplicated Permission registry: ${all[id]}") + throw DuplicatedPermissionRegistrationException("Duplicated Permission registry: ${all[id]}") } return new } @@ -64,7 +64,7 @@ public object AllDenyPermissionService : PermissionService { ): PermissionImpl { val new = PermissionImpl(id, description, base) if (all.putIfAbsent(id, new) != null) { - throw DuplicatedRegistrationException("Duplicated Permission registry: ${all[id]}") + throw DuplicatedPermissionRegistrationException("Duplicated Permission registry: ${all[id]}") } return new } @@ -80,7 +80,7 @@ public object AllDenyPermissionService : PermissionService { } @ExperimentalPermission -public object BuiltInPermissionService : AbstractConcurrentPermissionService(), +internal object BuiltInPermissionService : AbstractConcurrentPermissionService(), PermissionService { @ExperimentalPermission diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Exceptions.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/DuplicatedPermissionRegistrationException.kt similarity index 63% rename from backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Exceptions.kt rename to backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/DuplicatedPermissionRegistrationException.kt index c8b358936..b521e1703 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Exceptions.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/DuplicatedPermissionRegistrationException.kt @@ -7,19 +7,12 @@ * https://github.com/mamoe/mirai/blob/master/LICENSE */ +@file:Suppress("unused") + package net.mamoe.mirai.console.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) -} - -@ExperimentalPermission -public open class DuplicatedRegistrationException : Exception { +public open class DuplicatedPermissionRegistrationException : Exception { public constructor() : super() public constructor(message: String?) : super(message) public constructor(message: String?, cause: Throwable?) : super(message, cause) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permissible.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permissible.kt index 3b5c53b4e..b970e50e5 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permissible.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permissible.kt @@ -25,70 +25,4 @@ import net.mamoe.mirai.console.command.CommandSender @ExperimentalPermission public interface Permissible { public val identifier: PermissibleIdentifier -} - - -@ExperimentalPermission("Classname is subject to change") -public interface PermissibleIdentifier { - public val parents: Array - - public companion object { - @ExperimentalPermission - public infix fun PermissibleIdentifier.grantedWith(with: PermissibleIdentifier): Boolean { - return allParentsWithSelf().any { it == with } - } - - internal fun PermissibleIdentifier.allParentsWithSelf(): Sequence { - return sequence { - yield(this@allParentsWithSelf) - yieldAll(parents.asSequence()) - } - } - } -} - -/** - * - */ -@ExperimentalPermission -public sealed class AbstractPermissibleIdentifier( - public final override vararg val parents: PermissibleIdentifier -) : PermissibleIdentifier { - public object AnyGroup : AbstractPermissibleIdentifier(AnyContact) - public data class ExactGroup(public val groupId: Long) : AbstractPermissibleIdentifier(AnyGroup) - - public data class AnyMember(public val groupId: Long) : AbstractPermissibleIdentifier(AnyMemberFromAnyGroup) - public object AnyMemberFromAnyGroup : AbstractPermissibleIdentifier(AnyUser) - public data class ExactMember( - public val groupId: Long, - public val memberId: Long - ) : AbstractPermissibleIdentifier(AnyMember(groupId), ExactUser(memberId)) - - public object AnyFriend : AbstractPermissibleIdentifier(AnyUser) - public data class ExactFriend( - public val id: Long - ) : AbstractPermissibleIdentifier(ExactUser(id)) - - public object AnyTemp : AbstractPermissibleIdentifier(AnyUser) - public data class ExactTemp( - public val groupId: Long, - public val id: Long - ) : AbstractPermissibleIdentifier(ExactUser(groupId)) // TODO: 2020/9/8 ExactMember ? - - public object AnyUser : AbstractPermissibleIdentifier(AnyContact) - public data class ExactUser( - public val id: Long - ) : AbstractPermissibleIdentifier(AnyUser) - - public object AnyContact : AbstractPermissibleIdentifier() - - public object Console : AbstractPermissibleIdentifier() -} - -@ExperimentalPermission -public inline fun Permissible.hasPermission(permission: Permission): Boolean = - PermissionService.run { permission.testPermission(this@hasPermission) } - -@ExperimentalPermission -public inline fun Permissible.hasPermission(permission: PermissionId): Boolean = - PermissionService.run { permission.testPermission(this@hasPermission) } +} \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissibleIdentifier.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissibleIdentifier.kt new file mode 100644 index 000000000..4b0ad769e --- /dev/null +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissibleIdentifier.kt @@ -0,0 +1,57 @@ +@file:Suppress("unused") + +package net.mamoe.mirai.console.permission + +@ExperimentalPermission("Classname is subject to change") +public interface PermissibleIdentifier { + public val parents: Array + + public companion object { + @ExperimentalPermission + public infix fun PermissibleIdentifier.grantedWith(with: PermissibleIdentifier): Boolean { + return allParentsWithSelf().any { it == with } + } + + internal fun PermissibleIdentifier.allParentsWithSelf(): Sequence { + return sequence { + yield(this@allParentsWithSelf) + yieldAll(parents.asSequence()) + } + } + } +} + +@ExperimentalPermission +public sealed class AbstractPermissibleIdentifier( + public final override vararg val parents: PermissibleIdentifier +) : PermissibleIdentifier { + public object AnyGroup : AbstractPermissibleIdentifier(AnyContact) + public data class ExactGroup(public val groupId: Long) : AbstractPermissibleIdentifier(AnyGroup) + + public data class AnyMember(public val groupId: Long) : AbstractPermissibleIdentifier(AnyMemberFromAnyGroup) + public object AnyMemberFromAnyGroup : AbstractPermissibleIdentifier(AnyUser) + public data class ExactMember( + public val groupId: Long, + public val memberId: Long + ) : AbstractPermissibleIdentifier(AnyMember(groupId), ExactUser(memberId)) + + public object AnyFriend : AbstractPermissibleIdentifier(AnyUser) + public data class ExactFriend( + public val id: Long + ) : AbstractPermissibleIdentifier(ExactUser(id)) + + public object AnyTemp : AbstractPermissibleIdentifier(AnyUser) + public data class ExactTemp( + public val groupId: Long, + public val id: Long + ) : AbstractPermissibleIdentifier(ExactUser(groupId)) // TODO: 2020/9/8 ExactMember ? + + public object AnyUser : AbstractPermissibleIdentifier(AnyContact) + public data class ExactUser( + public val id: Long + ) : AbstractPermissibleIdentifier(AnyUser) + + public object AnyContact : AbstractPermissibleIdentifier() + + public object Console : AbstractPermissibleIdentifier() +} \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionGroup.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionGroup.kt deleted file mode 100644 index 115d76175..000000000 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionGroup.kt +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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 idNamespace: PermissionIdNamespace, -) { - @ExperimentalPermission - public inner class PermissionBuilder { - @JvmField - internal var description: String = "" - - @JvmField - internal var basePermission: PermissionId? = null - - @JvmField - internal var permissionChecker: PermissionChecker? = null - - public fun description(description: String): PermissionBuilder = apply { this.description = description } - public fun dependsOn(basePermission: PermissionId?): PermissionBuilder = - apply { this.basePermission = basePermission } - - public fun dependsOn(basePermission: Permission?): PermissionBuilder = - apply { this.basePermission = basePermission?.id } - - public fun basePermission(basePermission: PermissionId?): PermissionBuilder = - apply { this.basePermission = basePermission } - - public fun basePermission(basePermission: Permission?): PermissionBuilder = - apply { this.basePermission = basePermission?.id } - - public fun defaults(permissionChecker: PermissionChecker?): PermissionBuilder = - apply { this.permissionChecker = permissionChecker } - - public fun build(property: KProperty<*>): Permission { - return PermissionService.INSTANCE.register( - idNamespace.permissionId(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) -} - diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionId.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionId.kt index a71b29924..e3f01f193 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionId.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionId.kt @@ -49,8 +49,3 @@ public data class PermissionId( } } -@ExperimentalPermission -public interface PermissionIdNamespace { - @ExperimentalPermission - public fun permissionId(id: String): PermissionId -} diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionChecker.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionIdNamespace.kt similarity index 71% rename from backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionChecker.kt rename to backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionIdNamespace.kt index 21fbb4c42..6ce0a93a5 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionChecker.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionIdNamespace.kt @@ -7,13 +7,10 @@ * 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 +public interface PermissionIdNamespace { + @ExperimentalPermission + public fun permissionId(id: String): PermissionId } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionService.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionService.kt index 7b704ae2f..77bb77cb0 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionService.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionService.kt @@ -13,8 +13,6 @@ package net.mamoe.mirai.console.permission import net.mamoe.mirai.console.extension.SingletonExtensionPoint.Companion.findSingleton import net.mamoe.mirai.console.extensions.PermissionServiceProvider -import net.mamoe.mirai.console.permission.PermissibleIdentifier.Companion.grantedWith -import java.util.concurrent.CopyOnWriteArrayList import kotlin.reflect.KClass /** @@ -37,7 +35,7 @@ public interface PermissionService

{ /////////////////////////////////////////////////////////////////////////// - @Throws(DuplicatedRegistrationException::class) + @Throws(DuplicatedPermissionRegistrationException::class) public fun register( id: PermissionId, description: String, @@ -59,59 +57,23 @@ public interface PermissionService

{ } @ExperimentalPermission -public abstract class AbstractConcurrentPermissionService

: PermissionService

{ - protected abstract val permissions: MutableMap - protected abstract val grantedPermissionsMap: MutableMap> +public inline fun Permissible.hasPermission(permission: Permission): Boolean = + PermissionService.run { permission.testPermission(this@hasPermission) } - protected abstract fun createPermission( - id: PermissionId, - description: String, - base: PermissionId? - ): P - - override fun get(id: PermissionId): P? = permissions[id] - - override fun register(id: PermissionId, description: String, base: PermissionId?): P { - grantedPermissionsMap[id] = CopyOnWriteArrayList() // mutations are not quite often performed - val instance = createPermission(id, description, base) - if (permissions.putIfAbsent(id, instance) != null) { - throw DuplicatedRegistrationException("Duplicated Permission registry. new: $instance, old: ${permissions[id]}") - } - return instance - } - - override fun grant(permissibleIdentifier: PermissibleIdentifier, permission: P) { - val id = permission.id - grantedPermissionsMap[id]?.add(permissibleIdentifier) - ?: error("Bad PermissionService implementation: grantedPermissionsMap[id] is null.") - } - - override fun deny(permissibleIdentifier: PermissibleIdentifier, permission: P) { - grantedPermissionsMap[permission.id]?.remove(permissibleIdentifier) - } - - public override fun getGrantedPermissions(permissible: Permissible): Sequence

= sequence

{ - for ((permissionIdentifier, permissibleIdentifiers) in grantedPermissionsMap) { - val myIdentifier = permissible.identifier - - val granted = - if (permissibleIdentifiers.isEmpty()) false - else permissibleIdentifiers.any { myIdentifier grantedWith it } - - if (granted) get(permissionIdentifier)?.let { yield(it) } - } - } -} +@ExperimentalPermission +public inline fun Permissible.hasPermission(permission: PermissionId): Boolean = + PermissionService.run { permission.testPermission(this@hasPermission) } +@JvmSynthetic @ExperimentalPermission public inline fun Permissible.getGrantedPermissions(): Sequence = PermissionService.INSTANCE.run { getGrantedPermissions(this@getGrantedPermissions) } - +@JvmSynthetic @ExperimentalPermission -public inline fun Permission.testPermission(permissible: Permissible): Boolean = +public fun Permission.testPermission(permissible: Permissible): Boolean = PermissionService.INSTANCE.run { require(permissionType.isInstance(this@testPermission)) { "Custom-constructed Permission instance is not allowed. " + @@ -124,8 +86,9 @@ public inline fun Permission.testPermission(permissible: Permissible): Boolean = testPermission(permissible, this@testPermission) } +@JvmSynthetic @ExperimentalPermission -public inline fun PermissionId.testPermission(permissible: Permissible): Boolean { +public fun PermissionId.testPermission(permissible: Permissible): Boolean { val p = PermissionService.INSTANCE[this] ?: return false return p.testPermission(permissible) } \ No newline at end of file