| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- package handler
- import (
- "net/http"
- "goflare/internal/database/queries"
- mw "goflare/internal/middleware"
- "github.com/gorilla/sessions"
- "github.com/labstack/echo/v4"
- "golang.org/x/crypto/bcrypt"
- )
- type AuthHandler struct {
- q *queries.Queries
- store sessions.Store
- }
- func NewAuthHandler(q *queries.Queries, store sessions.Store) *AuthHandler {
- return &AuthHandler{q: q, store: store}
- }
- type credentials struct {
- Username string `json:"username"`
- Password string `json:"password"`
- }
- func (h *AuthHandler) Setup(c echo.Context) error {
- count, err := h.q.CountUsers(c.Request().Context())
- if err != nil {
- return c.JSON(http.StatusInternalServerError, map[string]string{"error": "db error"})
- }
- if count > 0 {
- return c.JSON(http.StatusBadRequest, map[string]string{"error": "user already exists"})
- }
- var cred credentials
- if err := c.Bind(&cred); err != nil {
- return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid request body"})
- }
- if cred.Username == "" || cred.Password == "" {
- return c.JSON(http.StatusBadRequest, map[string]string{"error": "username and password required"})
- }
- hash, err := bcrypt.GenerateFromPassword([]byte(cred.Password), bcrypt.DefaultCost)
- if err != nil {
- return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to hash password"})
- }
- user, err := h.q.CreateUser(c.Request().Context(), queries.CreateUserParams{
- Username: cred.Username,
- PasswordHash: string(hash),
- })
- if err != nil {
- return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to create user"})
- }
- return c.JSON(http.StatusCreated, map[string]string{
- "message": "user created",
- "username": user.Username,
- })
- }
- func (h *AuthHandler) Login(c echo.Context) error {
- var cred credentials
- if err := c.Bind(&cred); err != nil {
- return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid request body"})
- }
- user, err := h.q.GetUserByUsername(c.Request().Context(), cred.Username)
- if err != nil {
- return c.JSON(http.StatusUnauthorized, map[string]string{"error": "invalid credentials"})
- }
- if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(cred.Password)); err != nil {
- return c.JSON(http.StatusUnauthorized, map[string]string{"error": "invalid credentials"})
- }
- sess, err := mw.GetSession(c, h.store)
- if err != nil {
- return c.JSON(http.StatusInternalServerError, map[string]string{"error": "session error"})
- }
- sess.Values[mw.UserIDKey] = user.ID
- if err := sess.Save(c.Request(), c.Response()); err != nil {
- return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to save session"})
- }
- return c.JSON(http.StatusOK, map[string]string{"message": "logged in"})
- }
- func (h *AuthHandler) Logout(c echo.Context) error {
- sess, err := mw.GetSession(c, h.store)
- if err != nil {
- return c.JSON(http.StatusInternalServerError, map[string]string{"error": "session error"})
- }
- sess.Options.MaxAge = -1
- if err := sess.Save(c.Request(), c.Response()); err != nil {
- return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to clear session"})
- }
- return c.JSON(http.StatusOK, map[string]string{"message": "logged out"})
- }
- func (h *AuthHandler) NeedsSetup(c echo.Context) error {
- count, err := h.q.CountUsers(c.Request().Context())
- if err != nil {
- return c.JSON(http.StatusInternalServerError, map[string]string{"error": "db error"})
- }
- return c.JSON(http.StatusOK, map[string]bool{"needs_setup": count == 0})
- }
|