mirror of
				https://github.com/GayPizzaSpecifications/foundation.git
				synced 2025-11-04 03:39:37 +00:00 
			
		
		
		
	DevUpdate Server for Test Server Updates
This commit is contained in:
		@ -1,6 +1,7 @@
 | 
			
		||||
package cloud.kubelet.foundation.core
 | 
			
		||||
 | 
			
		||||
import cloud.kubelet.foundation.core.command.*
 | 
			
		||||
import cloud.kubelet.foundation.core.devupdate.DevUpdateServer
 | 
			
		||||
import cloud.kubelet.foundation.core.persist.PersistentStore
 | 
			
		||||
import cloud.kubelet.foundation.core.persist.setAllProperties
 | 
			
		||||
import io.papermc.paper.event.player.AsyncChatEvent
 | 
			
		||||
@ -19,6 +20,8 @@ import java.util.concurrent.ConcurrentHashMap
 | 
			
		||||
class FoundationCorePlugin : JavaPlugin(), Listener {
 | 
			
		||||
  internal val persistentStores = ConcurrentHashMap<String, PersistentStore>()
 | 
			
		||||
  private lateinit var _pluginDataPath: Path
 | 
			
		||||
  private lateinit var chatLogStore: PersistentStore
 | 
			
		||||
  private lateinit var devUpdateServer: DevUpdateServer
 | 
			
		||||
 | 
			
		||||
  var pluginDataPath: Path
 | 
			
		||||
    /**
 | 
			
		||||
@ -40,8 +43,6 @@ class FoundationCorePlugin : JavaPlugin(), Listener {
 | 
			
		||||
   */
 | 
			
		||||
  fun getPersistentStore(name: String) = persistentStores.getOrPut(name) { PersistentStore(this, name) }
 | 
			
		||||
 | 
			
		||||
  private lateinit var chatLogStore: PersistentStore
 | 
			
		||||
 | 
			
		||||
  override fun onEnable() {
 | 
			
		||||
    pluginDataPath = dataFolder.toPath()
 | 
			
		||||
    val backupPath = pluginDataPath.resolve(BACKUPS_DIRECTORY)
 | 
			
		||||
@ -67,11 +68,14 @@ class FoundationCorePlugin : JavaPlugin(), Listener {
 | 
			
		||||
    log.info("Features:")
 | 
			
		||||
    Util.printFeatureStatus(log, "Backup", BACKUP_ENABLED)
 | 
			
		||||
    chatLogStore = getPersistentStore("chat-logs")
 | 
			
		||||
    devUpdateServer = DevUpdateServer(this)
 | 
			
		||||
    devUpdateServer.enable()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  override fun onDisable() {
 | 
			
		||||
    persistentStores.values.forEach { store -> store.close() }
 | 
			
		||||
    persistentStores.clear()
 | 
			
		||||
    devUpdateServer.disable()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private fun registerCommandExecutor(name: String, executor: CommandExecutor) {
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,10 @@
 | 
			
		||||
package cloud.kubelet.foundation.core.devupdate
 | 
			
		||||
 | 
			
		||||
import kotlinx.serialization.Serializable
 | 
			
		||||
 | 
			
		||||
@Serializable
 | 
			
		||||
class DevUpdateConfig(
 | 
			
		||||
  val port: Int = 8484,
 | 
			
		||||
  val token: String,
 | 
			
		||||
  val ipAllowList: List<String> = listOf("*")
 | 
			
		||||
)
 | 
			
		||||
@ -0,0 +1,89 @@
 | 
			
		||||
package cloud.kubelet.foundation.core.devupdate
 | 
			
		||||
 | 
			
		||||
import cloud.kubelet.foundation.core.FoundationCorePlugin
 | 
			
		||||
import cloud.kubelet.foundation.core.Util
 | 
			
		||||
import com.charleskorn.kaml.Yaml
 | 
			
		||||
import com.sun.net.httpserver.HttpExchange
 | 
			
		||||
import com.sun.net.httpserver.HttpServer
 | 
			
		||||
import java.net.InetSocketAddress
 | 
			
		||||
import kotlin.io.path.inputStream
 | 
			
		||||
 | 
			
		||||
class DevUpdateServer(val plugin: FoundationCorePlugin) {
 | 
			
		||||
  private lateinit var config: DevUpdateConfig
 | 
			
		||||
  private var server: HttpServer? = null
 | 
			
		||||
 | 
			
		||||
  fun enable() {
 | 
			
		||||
    val configPath = Util.copyDefaultConfig<FoundationCorePlugin>(
 | 
			
		||||
      plugin.slF4JLogger,
 | 
			
		||||
      plugin.pluginDataPath,
 | 
			
		||||
      "devupdate.yaml"
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    config = Yaml.default.decodeFromStream(DevUpdateConfig.serializer(), configPath.inputStream())
 | 
			
		||||
    start()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private fun start() {
 | 
			
		||||
    if (config.token.isEmpty()) {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (config.token.length < 8) {
 | 
			
		||||
      plugin.slF4JLogger.warn("DevUpdate Token was too short (must be 8 or more characters)")
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    val server = HttpServer.create()
 | 
			
		||||
    server.createContext("/").setHandler { exchange ->
 | 
			
		||||
      val ip = exchange.remoteAddress.address.hostAddress
 | 
			
		||||
      if (!config.ipAllowList.contains("*") && !config.ipAllowList.contains(ip)) {
 | 
			
		||||
        plugin.slF4JLogger.warn("DevUpdate Server received request from IP $ip which is not allowed.")
 | 
			
		||||
        exchange.close()
 | 
			
		||||
        return@setHandler
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      plugin.slF4JLogger.info("DevUpdate Server Request $ip ${exchange.requestMethod} ${exchange.requestURI.path}")
 | 
			
		||||
      if (exchange.requestMethod != "POST") {
 | 
			
		||||
        exchange.respond(405, "Method not allowed.")
 | 
			
		||||
        return@setHandler
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (exchange.requestURI.path != "/webhook/update") {
 | 
			
		||||
        exchange.respond(404, "Not Found.")
 | 
			
		||||
        return@setHandler
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (exchange.requestURI.query != config.token) {
 | 
			
		||||
        exchange.respond(401, "Unauthorized.")
 | 
			
		||||
        return@setHandler
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      exchange.respond(200, "Success.")
 | 
			
		||||
      plugin.server.scheduler.runTask(plugin) { ->
 | 
			
		||||
        plugin.slF4JLogger.info("DevUpdate Server Restart")
 | 
			
		||||
        try {
 | 
			
		||||
          plugin.server.dispatchCommand(plugin.server.consoleSender, "fupdate")
 | 
			
		||||
          plugin.server.dispatchCommand(plugin.server.consoleSender, "stop")
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
          plugin.slF4JLogger.error("DevUpdate Server failed to update server.", e)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    server.bind(InetSocketAddress("0.0.0.0", config.port), 0)
 | 
			
		||||
    server.start()
 | 
			
		||||
    this.server = server
 | 
			
		||||
    plugin.slF4JLogger.info("DevUpdate Server listening on port ${config.port}")
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fun disable() {
 | 
			
		||||
    server?.stop(0)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private fun HttpExchange.respond(code: Int, content: String) {
 | 
			
		||||
    val encoded = content.encodeToByteArray()
 | 
			
		||||
    sendResponseHeaders(code, encoded.size.toLong())
 | 
			
		||||
    responseBody.write(encoded)
 | 
			
		||||
    responseBody.close()
 | 
			
		||||
    close()
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								foundation-core/src/main/resources/devupdate.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								foundation-core/src/main/resources/devupdate.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
# Server port to listen on.
 | 
			
		||||
port: 8484
 | 
			
		||||
 | 
			
		||||
# An authentication token. Should be random and 8 or more characters.
 | 
			
		||||
# If empty, the DevUpdate server is not enabled.
 | 
			
		||||
token: ""
 | 
			
		||||
 | 
			
		||||
# IP address allow list.
 | 
			
		||||
# If * is specified, all addresses are allowed.
 | 
			
		||||
# Specify IP addresses as a string that should be allowed to update the server.
 | 
			
		||||
ipAllowList:
 | 
			
		||||
  - "*"
 | 
			
		||||
		Reference in New Issue
	
	Block a user