package handlers import ( "github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3/middleware/session" "lmika.dev/lmika/weiro/config" "lmika.dev/lmika/weiro/models" "lmika.dev/lmika/weiro/services/auth" ) type LoginHandler struct { Config config.Config AuthService *auth.Service } func (lh *LoginHandler) Login(c fiber.Ctx) error { if lh.Config.LoginLocked { return c.Status(fiber.StatusForbidden).SendString("Login is locked") } loginChallenge := models.NewNanoID() sess := session.FromContext(c) sess.Set("_login_challenge", loginChallenge) c.Render("login/login", fiber.Map{ "challenge": loginChallenge, }, "layouts/bare") return nil } func (lh *LoginHandler) Logout(c fiber.Ctx) error { sess := session.FromContext(c) sess.Destroy() return c.Redirect().To("/login") } func (lh *LoginHandler) DoLogin(c fiber.Ctx) error { var req struct { Username string `form:"username"` Password string `form:"password"` LoginChallenge string `form:"_login_challenge"` } if err := c.Bind().Body(&req); err != nil { return c.Status(fiber.StatusBadRequest).SendString("Failed to parse request body") } if req.Username == "" || req.Password == "" { return c.Status(fiber.StatusBadRequest).SendString("Username and password are required") } sess := session.FromContext(c) challenge, _ := sess.Get("_login_challenge").(string) if challenge != req.LoginChallenge { return c.Redirect().To("/login") } user, err := lh.AuthService.Login(c.Context(), req.Username, req.Password) if err != nil { return c.Status(fiber.StatusInternalServerError).SendString("Failed to login") } if err := sess.Regenerate(); err != nil { return c.Status(fiber.StatusInternalServerError).SendString("Failed to login") } sess.Set("user_id", user.ID) return c.Redirect().To("/") }