Files
AquaDX/src/main/java/icu/samnyan/aqua/net/UserRegistrar.kt
2024-02-19 03:07:32 -05:00

69 lines
2.7 KiB
Kotlin

package icu.samnyan.aqua.net
import ext.*
import icu.samnyan.aqua.net.db.AquaNetUser
import icu.samnyan.aqua.net.db.AquaNetUserRepo
import icu.samnyan.aqua.net.components.GeoIP
import icu.samnyan.aqua.net.components.TurnstileService
import jakarta.servlet.http.HttpServletRequest
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("/api/v2/user")
class UserRegistrar(
val userRepo: AquaNetUserRepo,
val hasher: PasswordEncoder,
val turnstileService: TurnstileService,
val geoIP: GeoIP
) {
/**
* Register a new user
*/
@PostMapping("/register")
suspend fun register(@RP username: Str, @RP email: Str, @RP password: Str,
@RP turnstile: Str, request: HttpServletRequest) {
val ip = geoIP.getIP(request)
// Check captcha
if (!turnstileService.validate(turnstile, ip)) 400 > "Invalid captcha"
// Check if email is valid
if (!email.isValidEmail()) 400 > "Invalid email"
// Check if user with the same email exists
if (async { userRepo.findByEmailIgnoreCase(email) != null })
400 > "User with email `$email` already exists"
// Check if username is valid
if (username.length < 2) 400 > "Username must be at least 2 letters"
if (username.length > 32) 400 > "Username too long (max 32 letters)"
if (username.contains(" ")) 400 > "Username cannot contain spaces"
// Check if username is within A-Za-z0-9_-~.
username.find { !it.isLetterOrDigit() && it != '_' && it != '-' && it != '~' && it != '.' }?.let {
400 > "Username cannot contain `$it`. Please only use letters (A-Z), numbers (0-9), and `_-~.` characters. " +
"You can set a display name later."
}
// Check if user with the same username exists
if (async { userRepo.findByUsernameIgnoreCase(username) != null })
400 > "User with username `$username` already exists"
// Validate password
if (password.length < 8) 400 > "Password must be at least 8 characters"
// GeoIP check to infer country
val country = geoIP.getCountry(ip)
val u = AquaNetUser(username = username, email = email, pwHash = hasher.encode(password),
regTime = millis(), lastLogin = millis(), country = country)
async { userRepo.save(u) }
// TODO: Send confirmation email
200 > "User created"
}
}