forked from Cookies_Github_mirror/AquaDX
[M] Move services to components package
This commit is contained in:
75
src/main/java/icu/samnyan/aqua/net/components/Email.kt
Normal file
75
src/main/java/icu/samnyan/aqua/net/components/Email.kt
Normal file
@@ -0,0 +1,75 @@
|
||||
package icu.samnyan.aqua.net.components
|
||||
|
||||
import ext.Bool
|
||||
import ext.Str
|
||||
import icu.samnyan.aqua.net.db.AquaNetUser
|
||||
import jakarta.annotation.PostConstruct
|
||||
import org.simplejavamail.api.mailer.Mailer
|
||||
import org.simplejavamail.email.EmailBuilder
|
||||
import org.simplejavamail.springsupport.SimpleJavaMailSpringSupport
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.annotation.Import
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "aqua-net.email")
|
||||
class EmailProperties {
|
||||
var enable: Bool = false
|
||||
|
||||
lateinit var senderName: Str
|
||||
|
||||
lateinit var senderAddr: Str
|
||||
}
|
||||
|
||||
/**
|
||||
* Email service. All email related operations should be placed here.
|
||||
*
|
||||
* Library Documentation: https://www.simplejavamail.org/
|
||||
*/
|
||||
@Service
|
||||
@Import(SimpleJavaMailSpringSupport::class)
|
||||
class EmailService(
|
||||
val mailer: Mailer,
|
||||
val props: EmailProperties,
|
||||
) {
|
||||
val log: Logger = LoggerFactory.getLogger(EmailService::class.java)
|
||||
|
||||
/**
|
||||
* Test the connection of the email service on startup
|
||||
*/
|
||||
@PostConstruct
|
||||
fun testConnection() {
|
||||
if (!props.enable) return
|
||||
|
||||
try {
|
||||
mailer.testConnection()
|
||||
log.info("Email Service Connected")
|
||||
} catch (e: Exception) {
|
||||
log.error("Email Service Connection Failed", e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a confirmation email to the user
|
||||
*/
|
||||
fun confirmationEmail(user: AquaNetUser) {
|
||||
|
||||
}
|
||||
|
||||
fun testEmail(addr: Str, name: Str) {
|
||||
if (!props.enable) return
|
||||
|
||||
log.info("Sending test email to $addr")
|
||||
mailer.sendMail(EmailBuilder.startingBlank()
|
||||
.from(props.senderName, props.senderAddr)
|
||||
.to(name, addr)
|
||||
.withSubject("Test Email")
|
||||
.withPlainText("This is a test email to check if AquaNet Email Works").buildEmail()).thenRun {
|
||||
log.info("Test email sent to $addr")
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
88
src/main/java/icu/samnyan/aqua/net/components/GeoIP.kt
Normal file
88
src/main/java/icu/samnyan/aqua/net/components/GeoIP.kt
Normal file
@@ -0,0 +1,88 @@
|
||||
package icu.samnyan.aqua.net.components
|
||||
|
||||
import com.maxmind.geoip2.DatabaseReader
|
||||
import com.maxmind.geoip2.exception.AddressNotFoundException
|
||||
import ext.Str
|
||||
import jakarta.annotation.PostConstruct
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.stereotype.Service
|
||||
import java.io.File
|
||||
import java.net.InetAddress
|
||||
import java.net.URL
|
||||
import java.nio.file.Files
|
||||
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "aqua-net.geoip")
|
||||
class GeoIPProperties {
|
||||
var geoLitePath: Str = "data/GeoLite2-Country.mmdb"
|
||||
var ipHeader: Str = ""
|
||||
}
|
||||
|
||||
@Service
|
||||
class GeoIP(
|
||||
val props: GeoIPProperties
|
||||
) {
|
||||
val log = LoggerFactory.getLogger(GeoIP::class.java)!!
|
||||
lateinit var geoLite: DatabaseReader
|
||||
|
||||
@PostConstruct
|
||||
fun onLoad() {
|
||||
// Check path exists
|
||||
if (!File(props.geoLitePath).exists()) {
|
||||
log.error("GeoIP Service is enabled but GeoLite2 database is not found, trying to download from GitHub.")
|
||||
|
||||
// Download from GitHub
|
||||
try {
|
||||
log.info("Downloading GeoLite2 database to ${props.geoLitePath}")
|
||||
URL("https://github.com/P3TERX/GeoLite.mmdb/raw/download/GeoLite2-Country.mmdb").openStream()
|
||||
.use { Files.copy(it, File(props.geoLitePath).toPath()) }
|
||||
} catch (e: Exception) {
|
||||
log.error("Failed to download GeoLite2 database", e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
geoLite = DatabaseReader.Builder(File(props.geoLitePath)).build()
|
||||
selfTest()
|
||||
log.info("GeoIP Service Enabled")
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the connection of the GeoIP service on startup
|
||||
*/
|
||||
fun selfTest() {
|
||||
try {
|
||||
// Test with Google's IP
|
||||
getCountry("172.217.165.14")
|
||||
} catch (e: Exception) {
|
||||
log.error("GeoIP Service Self Test Failed", e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the IP address from a request
|
||||
*/
|
||||
fun getIP(request: HttpServletRequest): Str =
|
||||
if (props.ipHeader.isEmpty()) request.remoteAddr else request.getHeader(props.ipHeader) ?: request.remoteAddr
|
||||
|
||||
/**
|
||||
* Get the country code from an IP address
|
||||
*/
|
||||
fun getCountry(ip: Str): Str
|
||||
{
|
||||
return try {
|
||||
val ipa = InetAddress.getByName(ip)
|
||||
geoLite.country(ipa)?.country?.isoCode ?: ""
|
||||
}
|
||||
catch (e: AddressNotFoundException) { "" }
|
||||
catch (e: Exception) {
|
||||
log.error("Failed to get country from IP $ip", e)
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
61
src/main/java/icu/samnyan/aqua/net/components/JWT.kt
Normal file
61
src/main/java/icu/samnyan/aqua/net/components/JWT.kt
Normal file
@@ -0,0 +1,61 @@
|
||||
package icu.samnyan.aqua.net.components
|
||||
|
||||
import ext.Str
|
||||
import icu.samnyan.aqua.net.db.AquaNetUser
|
||||
import icu.samnyan.aqua.net.db.AquaNetUserRepo
|
||||
import io.jsonwebtoken.JwtParser
|
||||
import io.jsonwebtoken.Jwts
|
||||
import io.jsonwebtoken.security.Keys
|
||||
import jakarta.annotation.PostConstruct
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.stereotype.Service
|
||||
import java.util.*
|
||||
import javax.crypto.SecretKey
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "aqua-net.jwt")
|
||||
class JWTProperties {
|
||||
var secret: Str = "Open Sesame!"
|
||||
}
|
||||
|
||||
@Service
|
||||
class JWT(
|
||||
val props: JWTProperties,
|
||||
val userRepo: AquaNetUserRepo
|
||||
) {
|
||||
val log = LoggerFactory.getLogger(JWT::class.java)!!
|
||||
lateinit var key: SecretKey
|
||||
lateinit var parser: JwtParser
|
||||
|
||||
@PostConstruct
|
||||
fun onLoad() {
|
||||
// Check secret
|
||||
if (props.secret == "Open Sesame!") {
|
||||
log.warn("USING DEFAULT JWT SECRET, PLEASE SET aqua-net.jwt IN CONFIGURATION")
|
||||
}
|
||||
|
||||
// Initialize key
|
||||
key = Keys.hmacShaKeyFor(props.secret.toByteArray())
|
||||
|
||||
// Create parser
|
||||
parser = Jwts.parser()
|
||||
.verifyWith(key)
|
||||
.build()
|
||||
|
||||
log.info("JWT Service Enabled")
|
||||
}
|
||||
|
||||
|
||||
fun gen(user: AquaNetUser): Str = Jwts.builder().header()
|
||||
.keyId("aqua-net")
|
||||
.and()
|
||||
.subject(user.auId.toString())
|
||||
.issuedAt(Date())
|
||||
.signWith(key)
|
||||
.compact()
|
||||
|
||||
fun parse(token: Str): AquaNetUser? =
|
||||
userRepo.findByAuId(parser.parseSignedClaims(token).payload.subject.toLong())
|
||||
}
|
||||
45
src/main/java/icu/samnyan/aqua/net/components/Turnstile.kt
Normal file
45
src/main/java/icu/samnyan/aqua/net/components/Turnstile.kt
Normal file
@@ -0,0 +1,45 @@
|
||||
package icu.samnyan.aqua.net.components
|
||||
|
||||
import ext.Bool
|
||||
import ext.HTTP
|
||||
import ext.Str
|
||||
import io.ktor.client.call.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.client.request.forms.*
|
||||
import io.ktor.http.*
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "aqua-net.turnstile")
|
||||
class TurnstileProperties {
|
||||
var enable: Bool = false
|
||||
|
||||
lateinit var secret: Str
|
||||
}
|
||||
|
||||
@Service
|
||||
class TurnstileService(val props: TurnstileProperties) {
|
||||
@Serializable
|
||||
data class Outcome(val success: Boolean)
|
||||
|
||||
suspend fun validate(captcha: Str?, ip: Str): Boolean {
|
||||
if (!props.enable) return true
|
||||
if (captcha == null) return false
|
||||
|
||||
val outcome: Outcome = HTTP.post("https://challenges.cloudflare.com/turnstile/v0/siteverify") {
|
||||
setBody(
|
||||
FormDataContent(Parameters.build {
|
||||
append("secret", props.secret)
|
||||
append("response", captcha)
|
||||
append("remoteip", ip)
|
||||
})
|
||||
)
|
||||
}.body()
|
||||
|
||||
return outcome.success
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user