mirror of
https://github.com/LamGC/ScalaBot.git
synced 2025-07-03 22:07:24 +00:00
refactor(config): 将与配置相关的内容迁移到 scalabot-meta 模块.
通过将配置迁移到单独的模块, 可以方便使用其他程序扩展 ScaleBot, 而不仅仅是让 ScaleBot 成为扩展的平台. BREAKING CHANGE: 与配置有关的 Class 移动到了 scalabot-meta 模块. 目前仅所有配置类(以 `Config` 结尾的 Class)和相应的序列化类(以 `Serializer` 结尾的)都迁移到了 meta 模块, 但其工具方法则作为扩展函数保留在 app 模块中. 这么做的好处是为了方便其他应用(例如 ScalaBot 外部管理程序)根据需要生成配置文件. scalabot-meta 将会作为依赖项发布, 可根据需要获取 ScalaBot-meta 生成 ScalaBot 的配置. 此次改动普通用户无需迁移.
This commit is contained in:
@ -1,50 +1,16 @@
|
||||
package net.lamgc.scalabot
|
||||
|
||||
import com.github.stefanbirkner.systemlambda.SystemLambda
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonObject
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import org.junit.jupiter.api.io.TempDir
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import kotlin.math.abs
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
internal class BotAccountTest {
|
||||
|
||||
@Test
|
||||
fun `id getter`() {
|
||||
val accountId = abs(Random().nextInt()).toLong()
|
||||
assertEquals(accountId, BotAccount("Test", "${accountId}:AAHErDroUTznQsOd_oZPJ6cQEj4Z5mGHO10", 0).id)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun deserializerTest() {
|
||||
val accountId = abs(Random().nextInt()).toLong()
|
||||
val creatorId = abs(Random().nextInt()).toLong()
|
||||
val botAccountJsonObject = Gson().fromJson(
|
||||
"""
|
||||
{
|
||||
"name": "TestBot",
|
||||
"token": "${accountId}:AAHErDroUTznQsOd_oZPJ6cQEj4Z5mGHO10",
|
||||
"creatorId": $creatorId
|
||||
}
|
||||
""".trimIndent(), JsonObject::class.java
|
||||
)
|
||||
val botAccount = Gson().fromJson(botAccountJsonObject, BotAccount::class.java)
|
||||
assertEquals(botAccountJsonObject["name"].asString, botAccount.name)
|
||||
assertEquals(botAccountJsonObject["token"].asString, botAccount.token)
|
||||
assertEquals(accountId, botAccount.id, "BotAccount ID does not match expectations.")
|
||||
assertEquals(creatorId, botAccount.creatorId)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal class AppPathsTest {
|
||||
|
||||
@Test
|
||||
|
@ -1,43 +0,0 @@
|
||||
@file:Suppress("PackageDirectoryMismatch")
|
||||
|
||||
package net.lamgc.scalabot.util
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParseException
|
||||
import com.google.gson.JsonPrimitive
|
||||
import org.eclipse.aether.artifact.DefaultArtifact
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
internal class ArtifactSerializerTest {
|
||||
|
||||
@Test
|
||||
fun badJsonType() {
|
||||
assertFailsWith<JsonParseException> { ArtifactSerializer.deserialize(JsonObject(), null, null) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Basic format serialization`() {
|
||||
val gav = "org.example.software:test:1.0.0-SNAPSHOT"
|
||||
val expectArtifact = DefaultArtifact(gav)
|
||||
val actualArtifact = DefaultArtifact(ArtifactSerializer.serialize(expectArtifact, null, null).asString)
|
||||
assertEquals(expectArtifact, actualArtifact)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Full format serialization`() {
|
||||
val gav = "org.example.software:test:war:javadoc:1.0.0-SNAPSHOT"
|
||||
val expectArtifact = DefaultArtifact(gav)
|
||||
val actualArtifact = DefaultArtifact(ArtifactSerializer.serialize(expectArtifact, null, null).asString)
|
||||
assertEquals(expectArtifact, actualArtifact)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun deserialize() {
|
||||
val gav = "org.example.software:test:1.0.0-SNAPSHOT"
|
||||
val expectArtifact = DefaultArtifact(gav)
|
||||
val actualArtifact = ArtifactSerializer.deserialize(JsonPrimitive(gav), null, null)
|
||||
assertEquals(expectArtifact, actualArtifact)
|
||||
}
|
||||
}
|
@ -1,325 +0,0 @@
|
||||
package util
|
||||
|
||||
import com.google.gson.*
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import net.lamgc.scalabot.MavenRepositoryConfig
|
||||
import net.lamgc.scalabot.util.AuthenticationSerializer
|
||||
import net.lamgc.scalabot.util.MavenRepositoryConfigSerializer
|
||||
import net.lamgc.scalabot.util.ProxyTypeSerializer
|
||||
import org.eclipse.aether.repository.Authentication
|
||||
import org.eclipse.aether.repository.AuthenticationContext
|
||||
import org.eclipse.aether.repository.Proxy
|
||||
import org.intellij.lang.annotations.Language
|
||||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.telegram.telegrambots.bots.DefaultBotOptions
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Type
|
||||
import java.net.URL
|
||||
import kotlin.test.*
|
||||
|
||||
internal class SerializersKtTest {
|
||||
|
||||
private val instance: Any
|
||||
private val method: Method
|
||||
|
||||
init {
|
||||
val clazz = Class.forName("net.lamgc.scalabot.util.SerializerUtils")
|
||||
method = clazz.getDeclaredMethod("checkJsonKey", JsonObject::class.java, String::class.java)
|
||||
method.isAccessible = true
|
||||
instance = clazz.getDeclaredField("INSTANCE").apply {
|
||||
isAccessible = true
|
||||
}.get(null)
|
||||
}
|
||||
|
||||
private fun invoke(json: JsonObject, key: String): String {
|
||||
try {
|
||||
return method.invoke(instance, json, key) as String
|
||||
} catch (e: InvocationTargetException) {
|
||||
throw e.targetException
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Json key checker test`() {
|
||||
assertThrows(JsonParseException::class.java) {
|
||||
invoke(JsonObject(), "NOT_EXIST_KEY")
|
||||
}
|
||||
assertThrows(JsonParseException::class.java) {
|
||||
invoke(JsonObject().apply { add("NULL_KEY", JsonNull.INSTANCE) }, "NULL_KEY")
|
||||
}
|
||||
assertThrows(JsonParseException::class.java) {
|
||||
invoke(JsonObject().apply { add("ARRAY_KEY", JsonArray()) }, "ARRAY_KEY")
|
||||
}
|
||||
assertThrows(JsonParseException::class.java) {
|
||||
invoke(JsonObject().apply { add("OBJECT_KEY", JsonObject()) }, "OBJECT_KEY")
|
||||
}
|
||||
|
||||
val expectKey = "TEST"
|
||||
val expectString = "testString"
|
||||
val json = JsonObject().apply { addProperty(expectKey, expectString) }
|
||||
|
||||
assertEquals(expectString, invoke(json, expectKey))
|
||||
}
|
||||
}
|
||||
|
||||
internal class ProxyTypeSerializerTest {
|
||||
|
||||
@Test
|
||||
fun `serialize test`() {
|
||||
for (type in DefaultBotOptions.ProxyType.values()) {
|
||||
assertEquals(
|
||||
JsonPrimitive(type.name), ProxyTypeSerializer.serialize(type, null, null),
|
||||
"ProxyType 序列化结果与预期不符."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `deserialize test`() {
|
||||
assertThrows(JsonParseException::class.java) {
|
||||
ProxyTypeSerializer.deserialize(JsonObject(), null, null)
|
||||
}
|
||||
assertThrows(JsonParseException::class.java) {
|
||||
ProxyTypeSerializer.deserialize(JsonArray(), null, null)
|
||||
}
|
||||
|
||||
assertThrows(JsonParseException::class.java) {
|
||||
ProxyTypeSerializer.deserialize(JsonPrimitive("NOT_IN_ENUM_VALUE"), null, null)
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
DefaultBotOptions.ProxyType.NO_PROXY,
|
||||
ProxyTypeSerializer.deserialize(JsonNull.INSTANCE, null, null)
|
||||
)
|
||||
|
||||
for (type in DefaultBotOptions.ProxyType.values()) {
|
||||
assertEquals(
|
||||
type, ProxyTypeSerializer.deserialize(JsonPrimitive(type.name), null, null),
|
||||
"ProxyType 反序列化结果与预期不符."
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
type, ProxyTypeSerializer.deserialize(JsonPrimitive(" ${type.name} "), null, null),
|
||||
"ProxyType 反序列化时未对 Json 字符串进行修剪(trim)."
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal class MavenRepositoryConfigSerializerTest {
|
||||
|
||||
@Test
|
||||
fun `unsupported json type deserialize test`() {
|
||||
assertThrows(JsonParseException::class.java) {
|
||||
MavenRepositoryConfigSerializer.deserialize(
|
||||
JsonArray(),
|
||||
MavenRepositoryConfig::class.java,
|
||||
TestJsonDeserializationContext
|
||||
)
|
||||
}
|
||||
assertThrows(JsonParseException::class.java) {
|
||||
MavenRepositoryConfigSerializer.deserialize(
|
||||
JsonNull.INSTANCE,
|
||||
MavenRepositoryConfig::class.java,
|
||||
TestJsonDeserializationContext
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `json primitive deserialize test`() {
|
||||
val expectRepoUrl = "https://repo.example.org/maven"
|
||||
val config = MavenRepositoryConfigSerializer.deserialize(
|
||||
JsonPrimitive(expectRepoUrl),
|
||||
MavenRepositoryConfig::class.java,
|
||||
TestJsonDeserializationContext
|
||||
)
|
||||
|
||||
assertNull(config.id)
|
||||
assertEquals(URL(expectRepoUrl), config.url)
|
||||
assertNull(config.proxy, "Proxy 默认值不为 null.")
|
||||
assertEquals("default", config.layout)
|
||||
assertTrue(config.enableReleases)
|
||||
assertTrue(config.enableSnapshots)
|
||||
assertNull(config.authentication)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `json object default deserialize test`() {
|
||||
val expectRepoUrl = "https://repo.example.org/maven"
|
||||
val jsonObject = JsonObject()
|
||||
jsonObject.addProperty("url", expectRepoUrl)
|
||||
val config = MavenRepositoryConfigSerializer.deserialize(
|
||||
jsonObject,
|
||||
MavenRepositoryConfig::class.java,
|
||||
TestJsonDeserializationContext
|
||||
)
|
||||
|
||||
assertNull(config.id)
|
||||
assertEquals(URL(expectRepoUrl), config.url)
|
||||
assertNull(config.proxy, "Proxy 默认值不为 null.")
|
||||
assertEquals("default", config.layout)
|
||||
assertTrue(config.enableReleases)
|
||||
assertTrue(config.enableSnapshots)
|
||||
assertNull(config.authentication)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `json object deserialize test`() {
|
||||
@Language("JSON5")
|
||||
val looksGoodJsonString = """
|
||||
{
|
||||
"id": "test-repository",
|
||||
"url": "https://repo.example.org/maven",
|
||||
"proxy": {
|
||||
"type": "http",
|
||||
"host": "127.0.1.1",
|
||||
"port": 10800
|
||||
},
|
||||
"layout": "default",
|
||||
"enableReleases": false,
|
||||
"enableSnapshots": true
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
val jsonObject = Gson().fromJson(looksGoodJsonString, JsonObject::class.java)
|
||||
var config = MavenRepositoryConfigSerializer.deserialize(
|
||||
jsonObject,
|
||||
MavenRepositoryConfig::class.java,
|
||||
TestJsonDeserializationContext
|
||||
)
|
||||
|
||||
assertEquals(jsonObject["id"].asString, config.id)
|
||||
assertEquals(URL(jsonObject["url"].asString), config.url)
|
||||
assertEquals(Proxy("http", "127.0.1.1", 10800), config.proxy)
|
||||
assertEquals(jsonObject["layout"].asString, config.layout)
|
||||
assertEquals(jsonObject["enableReleases"].asBoolean, config.enableReleases)
|
||||
assertEquals(jsonObject["enableSnapshots"].asBoolean, config.enableSnapshots)
|
||||
|
||||
// ------------------------------------
|
||||
|
||||
jsonObject.add("proxy", JsonNull.INSTANCE)
|
||||
jsonObject.remove("layout")
|
||||
|
||||
config = MavenRepositoryConfigSerializer.deserialize(
|
||||
jsonObject,
|
||||
MavenRepositoryConfig::class.java,
|
||||
TestJsonDeserializationContext
|
||||
)
|
||||
|
||||
assertEquals(jsonObject["id"].asString, config.id)
|
||||
assertEquals(URL(jsonObject["url"].asString), config.url)
|
||||
assertNull(config.proxy)
|
||||
assertEquals("default", config.layout)
|
||||
assertEquals(jsonObject["enableReleases"].asBoolean, config.enableReleases)
|
||||
assertEquals(jsonObject["enableSnapshots"].asBoolean, config.enableSnapshots)
|
||||
|
||||
// ------------------------------------
|
||||
|
||||
jsonObject.add("authentication", JsonArray())
|
||||
jsonObject.add("layout", mockk<JsonPrimitive> {
|
||||
every { asString }.returns(null)
|
||||
})
|
||||
|
||||
config = MavenRepositoryConfigSerializer.deserialize(
|
||||
jsonObject,
|
||||
MavenRepositoryConfig::class.java,
|
||||
TestJsonDeserializationContext
|
||||
)
|
||||
|
||||
assertEquals(jsonObject["id"].asString, config.id)
|
||||
assertEquals(URL(jsonObject["url"].asString), config.url)
|
||||
assertNull(config.proxy)
|
||||
assertEquals("default", config.layout)
|
||||
assertEquals(jsonObject["enableReleases"].asBoolean, config.enableReleases)
|
||||
assertEquals(jsonObject["enableSnapshots"].asBoolean, config.enableSnapshots)
|
||||
assertNull(config.authentication)
|
||||
|
||||
// ------------------------------------
|
||||
|
||||
jsonObject.add("authentication", JsonObject().apply {
|
||||
addProperty("username", "testUsername")
|
||||
addProperty("password", "testPassword")
|
||||
})
|
||||
|
||||
config = MavenRepositoryConfigSerializer.deserialize(
|
||||
jsonObject,
|
||||
MavenRepositoryConfig::class.java,
|
||||
TestJsonDeserializationContext
|
||||
)
|
||||
|
||||
assertEquals(jsonObject["id"].asString, config.id)
|
||||
assertEquals(URL(jsonObject["url"].asString), config.url)
|
||||
assertNull(config.proxy)
|
||||
assertEquals("default", config.layout)
|
||||
assertEquals(jsonObject["enableReleases"].asBoolean, config.enableReleases)
|
||||
assertEquals(jsonObject["enableSnapshots"].asBoolean, config.enableSnapshots)
|
||||
assertNotNull(config.authentication)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private object TestJsonDeserializationContext : JsonDeserializationContext {
|
||||
|
||||
private val gson = GsonBuilder()
|
||||
.registerTypeAdapter(Authentication::class.java, AuthenticationSerializer)
|
||||
.create()
|
||||
|
||||
override fun <T : Any?> deserialize(json: JsonElement, typeOfT: Type): T {
|
||||
return gson.fromJson(json, typeOfT)
|
||||
}
|
||||
}
|
||||
|
||||
internal class AuthenticationSerializerTest {
|
||||
|
||||
@Test
|
||||
fun `deserialize test`() {
|
||||
assertThrows(JsonParseException::class.java) {
|
||||
AuthenticationSerializer.deserialize(
|
||||
JsonNull.INSTANCE,
|
||||
Authentication::class.java, TestJsonDeserializationContext
|
||||
)
|
||||
}
|
||||
assertThrows(JsonParseException::class.java) {
|
||||
AuthenticationSerializer.deserialize(
|
||||
JsonArray(),
|
||||
Authentication::class.java, TestJsonDeserializationContext
|
||||
)
|
||||
}
|
||||
assertThrows(JsonParseException::class.java) {
|
||||
AuthenticationSerializer.deserialize(
|
||||
JsonPrimitive("A STRING"),
|
||||
Authentication::class.java, TestJsonDeserializationContext
|
||||
)
|
||||
}
|
||||
|
||||
val expectJsonObject = JsonObject().apply {
|
||||
addProperty("username", "testUsername")
|
||||
addProperty("password", "testPassword")
|
||||
}
|
||||
|
||||
val mockContext = mockk<AuthenticationContext> {
|
||||
every { put(any(), any()) }.answers { }
|
||||
}
|
||||
|
||||
val result = AuthenticationSerializer.deserialize(
|
||||
expectJsonObject,
|
||||
Authentication::class.java, TestJsonDeserializationContext
|
||||
)
|
||||
|
||||
assertNotNull(result)
|
||||
result.fill(mockContext, "username", null)
|
||||
result.fill(mockContext, "password", null)
|
||||
|
||||
verify {
|
||||
mockContext.put("username", "testUsername")
|
||||
mockContext.put("password", "testPassword".toCharArray())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
package net.lamgc.scalabot.util
|
||||
|
||||
import com.google.gson.*
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import kotlin.test.*
|
||||
|
||||
class UsernameAuthenticatorTest {
|
||||
|
||||
@Test
|
||||
fun checkCredentialsTest() {
|
||||
val authenticator = UsernameAuthenticator("testUser", "testPassword")
|
||||
assertTrue(authenticator.checkCredentials("testUser", "testPassword"))
|
||||
assertFalse(authenticator.checkCredentials("falseUser", "testPassword"))
|
||||
assertFalse(authenticator.checkCredentials("testUser", "falsePassword"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun toJsonObjectTest() {
|
||||
val authenticator = UsernameAuthenticator("testUser", "testPassword")
|
||||
val jsonObject = authenticator.toJsonObject()
|
||||
assertEquals("testUser", jsonObject["username"]?.asString)
|
||||
assertEquals("testPassword", jsonObject["password"]?.asString)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun equalsTest() {
|
||||
val authenticator = UsernameAuthenticator("testUser", "testPassword")
|
||||
assertEquals(authenticator, UsernameAuthenticator("testUser", "testPassword"))
|
||||
assertEquals(authenticator.hashCode(), UsernameAuthenticator("testUser", "testPassword").hashCode())
|
||||
assertNotEquals(authenticator, UsernameAuthenticator("testUser", "falsePassword"))
|
||||
assertNotEquals(authenticator.hashCode(), UsernameAuthenticator("testUser", "falsePassword").hashCode())
|
||||
assertNotEquals(authenticator, UsernameAuthenticator("falseUser", "testPassword"))
|
||||
assertNotEquals(authenticator.hashCode(), UsernameAuthenticator("falseUser", "testPassword").hashCode())
|
||||
assertNotEquals(authenticator, UsernameAuthenticator("falseUser", "falsePassword"))
|
||||
assertNotEquals(authenticator.hashCode(), UsernameAuthenticator("falseUser", "falsePassword").hashCode())
|
||||
assertFalse(authenticator.equals(null))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class UsernameAuthenticatorSerializerTest {
|
||||
|
||||
@Test
|
||||
fun serializeTest() {
|
||||
val authenticator = UsernameAuthenticator("testUser", "testPassword")
|
||||
val jsonElement = UsernameAuthenticatorSerializer.serialize(authenticator, null, null)
|
||||
assertTrue(jsonElement.isJsonObject)
|
||||
val jsonObject = jsonElement.asJsonObject
|
||||
assertEquals("testUser", jsonObject["username"]?.asString)
|
||||
assertEquals("testPassword", jsonObject["password"]?.asString)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun deserializeTest() {
|
||||
assertThrows<JsonParseException> {
|
||||
UsernameAuthenticatorSerializer.deserialize(JsonArray(), null, null)
|
||||
}
|
||||
assertThrows<JsonParseException> {
|
||||
UsernameAuthenticatorSerializer.deserialize(JsonPrimitive(""), null, null)
|
||||
}
|
||||
assertNull(UsernameAuthenticatorSerializer.deserialize(JsonNull.INSTANCE, null, null))
|
||||
assertThrows<JsonParseException> {
|
||||
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
||||
addProperty("username", "testUser")
|
||||
}, null, null)
|
||||
}
|
||||
assertThrows<JsonParseException> {
|
||||
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
||||
addProperty("username", "testUser")
|
||||
add("password", JsonArray())
|
||||
}, null, null)
|
||||
}
|
||||
assertThrows<JsonParseException> {
|
||||
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
||||
addProperty("password", "testPassword")
|
||||
}, null, null)
|
||||
}
|
||||
assertThrows<JsonParseException> {
|
||||
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
||||
add("username", JsonArray())
|
||||
addProperty("password", "testPassword")
|
||||
}, null, null)
|
||||
}
|
||||
assertThrows<JsonParseException> {
|
||||
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
||||
addProperty("username", "")
|
||||
addProperty("password", "")
|
||||
}, null, null)
|
||||
}
|
||||
assertThrows<JsonParseException> {
|
||||
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
||||
addProperty("username", "testUser")
|
||||
addProperty("password", "")
|
||||
}, null, null)
|
||||
}
|
||||
assertThrows<JsonParseException> {
|
||||
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
||||
addProperty("username", "")
|
||||
addProperty("password", "testPassword")
|
||||
}, null, null)
|
||||
}
|
||||
|
||||
val authenticator = UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
||||
addProperty("username", "testUser")
|
||||
addProperty("password", "testPassword")
|
||||
}, null, null)
|
||||
assertNotNull(authenticator)
|
||||
|
||||
assertTrue(authenticator.checkCredentials("testUser", "testPassword"))
|
||||
assertFalse(authenticator.checkCredentials("falseUser", "testPassword"))
|
||||
assertFalse(authenticator.checkCredentials("testUser", "falsePassword"))
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user