diff --git a/.env.example b/.env.example index 99fb2cad686269647582da680dd220e69eab7dd1..ba76ff58b1d5c2efc18274ce16393ec2077fd99d 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,6 @@ ALLOWED_ORIGINS=https://hizla.io DB=db VERBOSE=1 -LISTEN_ADDR=127.0.0.1:3000 \ No newline at end of file +LISTEN_ADDR=127.0.0.1:3000 +HCAPTCHA_SITE_KEY=unset +HCAPTCHA_SECRET=unset \ No newline at end of file diff --git a/app.go b/app.go index e1a11d0cc03133547a407cba2ce239706d3d75d0..3fdf149c5aac989c3009b63a914b94938b49fbf1 100644 --- a/app.go +++ b/app.go @@ -36,10 +36,8 @@ func serve(sig chan os.Signal, db *leveldb.DB) error { // /register routeRegister(app, db) - // Graceful shutdown - app.Use(func(c fiber.Ctx) error { - return c.Next() - }) + // /hcaptcha-site-key + routeHCaptchaSiteKey(app) // graceful shutdown go func() { diff --git a/conf.go b/conf.go index 15d3daeacd17ceaf20eca91e4e91a49109ddbc5f..8790fc9c7861e56b2c21d0f9dd0fa3afacb14766 100644 --- a/conf.go +++ b/conf.go @@ -9,6 +9,8 @@ const ( dbPath uint8 = iota listenAddr allowedOrigins + hCaptchaSecret + hCaptchaSiteKey verboseLogging confLen ) @@ -18,6 +20,8 @@ var confEnv = [confLen][2]string{ {"DB", "db"}, {"LISTEN_ADDR", "127.0.0.1:3000"}, {"ALLOWED_ORIGINS", "https://hizla.io"}, + {"HCAPTCHA_SECRET", "unset"}, + {"HCAPTCHA_SITE_KEY", "unset"}, {"VERBOSE", "1"}, } diff --git a/register.go b/register.go index 7276a3dfb9a4e07a3b529f6fb7fbdff34a9303ca..84a00f9ebee65d42c25c745fec40244ffdf68966 100644 --- a/register.go +++ b/register.go @@ -4,6 +4,7 @@ import ( "log" "regexp" "github.com/gofiber/fiber/v3" + "github.com/gofiber/contrib/hcaptcha" "github.com/syndtr/goleveldb/leveldb" ) @@ -13,9 +14,27 @@ type registration struct { Email string `json:"email"` } +// Middleware to conditionally apply hCaptcha +func conditionalCaptcha(captcha fiber.Handler) fiber.Handler { + return func(c fiber.Ctx) error { + if conf[hCaptchaSecret] == "unset" { + if verbose { + log.Printf("Captcha bypassed for %q", c.IP()) + } + return c.Next() + } + return captcha(c) + } +} + // Waitlist registration route func routeRegister(app *fiber.App, db *leveldb.DB) { - app.Post("/register", func(c fiber.Ctx) error { + + captcha := hcaptcha.New(hcaptcha.Config{ + SecretKey: conf[hCaptchaSecret], + }) + + app.Post("/register", conditionalCaptcha(captcha), func(c fiber.Ctx) error { req := new(registration) // Parse and validate the request @@ -66,4 +85,18 @@ func routeRegister(app *fiber.App, db *leveldb.DB) { "message": "Email registered successfully", }) }) +} + +// Route to expose hCaptcha site key +func routeHCaptchaSiteKey(app *fiber.App) { + app.Get("/hcaptcha-site-key", func(c fiber.Ctx) error { + if conf[hCaptchaSiteKey] == "unset" { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "message": "hCaptcha site key not configured", + }) + } + return c.JSON(fiber.Map{ + "hcaptcha_site_key": conf[hCaptchaSiteKey], + }) + }) } \ No newline at end of file