code simplification

This commit is contained in:
2025-01-09 00:05:00 +08:00
parent 0fdb37fb54
commit d5a2c4a591
24 changed files with 11 additions and 1853 deletions

View File

@@ -61,14 +61,6 @@ abstract class AbstractNettyHttpAuthenticator(private val authorizer : Authorize
return String(Base64.getEncoder().encode(concat(hash, actualSalt)))
}
// fun decodePasswordHash(passwordHash : String) : Pair<String, String> {
// return passwordHash.indexOf(':')
// .takeIf { it > 0 }
// ?.let { sep ->
// passwordHash.substring(0, sep) to passwordHash.substring(sep)
// } ?: throw IllegalArgumentException("Failed to decode password hash")
// }
fun decodePasswordHash(passwordHash : String) : Pair<ByteArray, ByteArray> {
val decoded = Base64.getDecoder().decode(passwordHash)
val hash = ByteArray(KEY_LENGTH / 8)

View File

@@ -46,9 +46,8 @@ import net.woggioni.gbcs.api.Cache
import net.woggioni.gbcs.api.Configuration
import net.woggioni.gbcs.api.Role
import net.woggioni.gbcs.api.exception.ContentTooLargeException
import net.woggioni.gbcs.base.GBCS
import net.woggioni.gbcs.base.Xml
import net.woggioni.gbcs.base.GBCS.toUrl
import net.woggioni.gbcs.base.Xml
import net.woggioni.gbcs.base.contextLogger
import net.woggioni.gbcs.base.debug
import net.woggioni.gbcs.base.info
@@ -76,7 +75,6 @@ import java.util.regex.Pattern
import javax.naming.ldap.LdapName
import javax.net.ssl.SSLEngine
import javax.net.ssl.SSLPeerUnverifiedException
import kotlin.io.path.absolute
class GradleBuildCacheServer(private val cfg: Configuration) {
@@ -540,7 +538,6 @@ class GradleBuildCacheServer(private val cfg: Configuration) {
}
fun loadConfiguration(args: Array<String>): Configuration {
// registerUrlProtocolHandler()
// Thread.currentThread().contextClassLoader = GradleBuildCacheServer::class.java.classLoader
val app = Application.builder("gbcs")
.configurationDirectoryEnvVar("GBCS_CONFIGURATION_DIR")

View File

@@ -1,309 +0,0 @@
package net.woggioni.gbcs.configuration
import net.woggioni.gbcs.api.Role
import java.nio.file.Path
import java.security.cert.X509Certificate
import java.time.Duration
@ConsistentCopyVisibility
data class Configuration private constructor(
val host: String,
val port: Int,
val serverPath: String?,
val users: Map<String, User>,
val groups: Map<String, Group>,
val cache: Cache,
val authentication : Authentication?,
val tls: Tls?,
val useVirtualThread: Boolean
) {
data class Group(val name: String, val roles: Set<Role>) {
override fun hashCode(): Int {
return name.hashCode()
}
}
data class User(val name: String, val password: String?, val groups: Set<Group>) {
override fun hashCode(): Int {
return name.hashCode()
}
val roles : Set<Role>
get() = groups.asSequence().flatMap { it.roles }.toSet()
}
fun interface UserExtractor {
fun extract(cert :X509Certificate) : User
}
fun interface GroupExtractor {
fun extract(cert :X509Certificate) : Group
}
data class Tls(
val keyStore: KeyStore?,
val trustStore: TrustStore?,
val verifyClients: Boolean,
)
data class KeyStore(
val file: Path,
val password: String?,
val keyAlias: String,
val keyPassword: String?
)
data class TrustStore(
val file: Path,
val password: String?,
val checkCertificateStatus: Boolean
)
data class TlsCertificateExtractor(val rdnType : String, val pattern : String)
interface Authentication
class BasicAuthentication : Authentication
data class ClientCertificateAuthentication(
val userExtractor: TlsCertificateExtractor?,
val groupExtractor: TlsCertificateExtractor?) : Authentication
interface Cache
data class FileSystemCache(val root: Path, val maxAge: Duration) : Cache
companion object {
fun of(
host: String,
port: Int,
serverPath: String?,
users: Map<String, User>,
groups: Map<String, Group>,
cache: Cache,
authentication : Authentication?,
tls: Tls?,
useVirtualThread: Boolean
) = Configuration(
host,
port,
serverPath?.takeIf { it.isNotEmpty() && it != "/" },
users,
groups,
cache,
authentication,
tls,
useVirtualThread
)
// fun parse(document: Document): Configuration {
// val cacheSerializers = ServiceLoader.load(Configuration::class.java.module.layer, CacheSerializer::class.java)
// .asSequence()
// .map {
// "${it.xmlType}:${it.xmlNamespace}" to it
// }.toMap()
// val root = document.documentElement
// var cache: Cache? = null
// var host = "127.0.0.1"
// var port = 11080
// var users = emptyMap<String, User>()
// var groups = emptyMap<String, Group>()
// var tls: Tls? = null
// val serverPath = root.getAttribute("path")
// val useVirtualThread = root.getAttribute("useVirtualThreads")
// .takeIf(String::isNotEmpty)
// ?.let(String::toBoolean) ?: false
// var authentication : Authentication? = null
// for (child in root.asIterable()) {
// when (child.nodeName) {
// "authorization" -> {
// for (gchild in child.asIterable()) {
// when (child.nodeName) {
// "users" -> {
// users = parseUsers(child)
// }
//
// "groups" -> {
// val pair = parseGroups(child, users)
// users = pair.first
// groups = pair.second
// }
// }
// }
// }
//
// "bind" -> {
// host = child.getAttribute("host")
// port = Integer.parseInt(child.getAttribute("port"))
// }
//
// "cache" -> {
// val type = child.getAttribute("xs:type")
// val serializer = cacheSerializers.get(type) ?: throw NotImplementedError()
// cache = serializer.deserialize(child)
//
// when(child.getAttribute("xs:type")) {
// "gbcs:fileSystemCacheType" -> {
// val cacheFolder = child.getAttribute("path")
// .takeIf(String::isNotEmpty)
// ?.let(Paths::get)
// ?: Paths.get(System.getProperty("user.home")).resolve(".gbcs")
// val maxAge = child.getAttribute("max-age")
// .takeIf(String::isNotEmpty)
// ?.let(Duration::parse)
// ?: Duration.ofDays(1)
// cache = FileSystemCache(cacheFolder, maxAge)
// }
// }
//// for (gchild in child.asIterable()) {
//// when (gchild.nodeName) {
//// "file-system-cache" -> {
//// val cacheFolder = gchild.getAttribute("path")
//// .takeIf(String::isNotEmpty)
//// ?.let(Paths::get)
//// ?: Paths.get(System.getProperty("user.home")).resolve(".gbcs")
//// val maxAge = gchild.getAttribute("max-age")
//// .takeIf(String::isNotEmpty)
//// ?.let(Duration::parse)
//// ?: Duration.ofDays(1)
//// cache = FileSystemCache(cacheFolder, maxAge)
//// }
//// }
//// }
// }
//
// "authentication" -> {
// for (gchild in child.asIterable()) {
// when (gchild.nodeName) {
// "basic" -> {
// authentication = BasicAuthentication()
// }
//
// "client-certificate" -> {
// var tlsExtractorUser : TlsCertificateExtractor? = null
// var tlsExtractorGroup : TlsCertificateExtractor? = null
// for (gchild in child.asIterable()) {
// when (gchild.nodeName) {
// "group-extractor" -> {
// val attrName = gchild.getAttribute("attribute-name")
// val pattern = gchild.getAttribute("pattern")
// tlsExtractorGroup = TlsCertificateExtractor(attrName, pattern)
// }
//
// "user-extractor" -> {
// val attrName = gchild.getAttribute("attribute-name")
// val pattern = gchild.getAttribute("pattern")
// tlsExtractorUser = TlsCertificateExtractor(attrName, pattern)
// }
// }
// }
// authentication = ClientCertificateAuthentication(tlsExtractorUser, tlsExtractorGroup)
// }
// }
// }
// }
//
// "tls" -> {
// val verifyClients = child.getAttribute("verify-clients")
// .takeIf(String::isNotEmpty)
// ?.let(String::toBoolean) ?: false
// var keyStore: KeyStore? = null
// var trustStore: TrustStore? = null
// for (granChild in child.asIterable()) {
// when (granChild.nodeName) {
// "keystore" -> {
// val keyStoreFile = Paths.get(granChild.getAttribute("file"))
// val keyStorePassword = granChild.getAttribute("password")
// .takeIf(String::isNotEmpty)
// val keyAlias = granChild.getAttribute("key-alias")
// val keyPassword = granChild.getAttribute("key-password")
// .takeIf(String::isNotEmpty)
// keyStore = KeyStore(
// keyStoreFile,
// keyStorePassword,
// keyAlias,
// keyPassword
// )
// }
//
// "truststore" -> {
// val trustStoreFile = Paths.get(granChild.getAttribute("file"))
// val trustStorePassword = granChild.getAttribute("password")
// .takeIf(String::isNotEmpty)
// val checkCertificateStatus = granChild.getAttribute("check-certificate-status")
// .takeIf(String::isNotEmpty)
// ?.let(String::toBoolean)
// ?: false
// trustStore = TrustStore(
// trustStoreFile,
// trustStorePassword,
// checkCertificateStatus
// )
// }
// }
// }
// tls = Tls(keyStore, trustStore, verifyClients)
// }
// }
// }
// return of(host, port, serverPath, users, groups, cache!!, authentication, tls, useVirtualThread)
// }
//
// private fun parseRoles(root: Element) = root.asIterable().asSequence().map {
// when (it.nodeName) {
// "reader" -> Role.Reader
// "writer" -> Role.Writer
// else -> throw UnsupportedOperationException("Illegal node '${it.nodeName}'")
// }
// }.toSet()
//
// private fun parseUserRefs(root: Element) = root.asIterable().asSequence().filter {
// it.nodeName == "user"
// }.map {
// it.getAttribute("ref")
// }.toSet()
//
// private fun parseUsers(root: Element): Map<String, User> {
// return root.asIterable().asSequence().filter {
// it.nodeName == "user"
// }.map { el ->
// val username = el.getAttribute("name")
// val password = el.getAttribute("password").takeIf(String::isNotEmpty)
// username to User(username, password, emptySet())
// }.toMap()
// }
//
// private fun parseGroups(root: Element, knownUsers : Map<String, User>): Pair<Map<String, User>, Map<String, Group>> {
// val userGroups = mutableMapOf<String, MutableSet<String>>()
// val groups = root.asIterable().asSequence().filter {
// it.nodeName == "group"
// }.map { el ->
// val groupName = el.getAttribute("name")
// var roles = emptySet<Role>()
// for (child in el.asIterable()) {
// when (child.nodeName) {
// "users" -> {
// parseUserRefs(child).mapNotNull(knownUsers::get).forEach { user ->
// userGroups.computeIfAbsent(user.name) {
// mutableSetOf()
// }.add(groupName)
// }
// }
// "roles" -> {
// roles = parseRoles(child)
// }
// }
// }
// groupName to Group(groupName, roles)
// }.toMap()
// val users = knownUsers.map { (name, user) ->
// name to User(name, user.password, userGroups[name]?.mapNotNull { groups[it] }?.toSet() ?: emptySet())
// }.toMap()
// return users to groups
// }
}
}

View File

@@ -16,6 +16,7 @@ import net.woggioni.gbcs.base.Xml.Companion.asIterable
import org.w3c.dom.Document
import org.w3c.dom.Element
import org.w3c.dom.TypeInfo
import java.lang.IllegalArgumentException
import java.nio.file.Paths
object Parser {
@@ -57,45 +58,12 @@ object Parser {
}
"cache" -> {
// val type = child.getAttribute("xs:type").split(":")
// val namespaceURI = child.lookupNamespaceURI(type[0])
// val typeName = type[1]
cache = (child as? TypeInfo)?.let { tf ->
cache = (child as TypeInfo).let { tf ->
val typeNamespace = tf.typeNamespace
val typeName = tf.typeName
CacheSerializers.index[typeNamespace to typeName]
}?.deserialize(child) ?: throw NotImplementedError()
// cache = serializer.deserialize(child)
// when(child.getAttribute("xs:type")) {
// "gbcs:fileSystemCacheType" -> {
// val cacheFolder = child.getAttribute("path")
// .takeIf(String::isNotEmpty)
// ?.let(Paths::get)
// ?: Paths.get(System.getProperty("user.home")).resolve(".gbcs")
// val maxAge = child.getAttribute("max-age")
// .takeIf(String::isNotEmpty)
// ?.let(Duration::parse)
// ?: Duration.ofDays(1)
// cache = FileSystemCache(cacheFolder, maxAge)
// }
// }
// for (gchild in child.asIterable()) {
// when (gchild.localName) {
// "file-system-cache" -> {
// val cacheFolder = gchild.getAttribute("path")
// .takeIf(String::isNotEmpty)
// ?.let(Paths::get)
// ?: Paths.get(System.getProperty("user.home")).resolve(".gbcs")
// val maxAge = gchild.getAttribute("max-age")
// .takeIf(String::isNotEmpty)
// ?.let(Duration::parse)
// ?: Duration.ofDays(1)
// cache = FileSystemCache(cacheFolder, maxAge)
// }
// }
// }
?: throw IllegalArgumentException("Cache provider for namespace '$typeNamespace' not found")
}.deserialize(child)
}
"authentication" -> {