Haystack/backend/auth/handler.go
2025-08-25 14:23:57 +01:00

107 lines
2.3 KiB
Go

package auth
import (
"database/sql"
"net/http"
"os"
"screenmark/screenmark/.gen/haystack/haystack/model"
"screenmark/screenmark/middleware"
"screenmark/screenmark/models"
"github.com/charmbracelet/log"
"github.com/go-chi/chi/v5"
)
type AuthHandler struct {
logger *log.Logger
user models.UserModel
auth Auth
}
type loginBody struct {
Email string `json:"email"`
}
type codeBody struct {
Email string `json:"email"`
Code string `json:"code"`
}
type codeReturn struct {
Access string `json:"access"`
Refresh string `json:"refresh"`
}
func (h *AuthHandler) login(body loginBody, w http.ResponseWriter, r *http.Request) {
err := h.auth.CreateCode(body.Email)
if err != nil {
middleware.WriteErrorInternal(h.logger, "could not create a code", w)
return
}
w.WriteHeader(http.StatusOK)
}
func (h *AuthHandler) code(body codeBody, w http.ResponseWriter, r *http.Request) {
if err := h.auth.UseCode(body.Email, body.Code); err != nil {
middleware.WriteErrorBadRequest(h.logger, "email or code are incorrect", w)
return
}
// TODO: we should only keep emails around for a little bit.
// Time to first login should be less than 10 minutes.
// So actually, they shouldn't be written to our database.
if exists := h.user.DoesUserExist(r.Context(), body.Email); !exists {
h.user.Save(r.Context(), model.Users{
Email: body.Email,
})
}
uuid, err := h.user.GetUserIdFromEmail(r.Context(), body.Email)
if err != nil {
middleware.WriteErrorBadRequest(h.logger, "failed to get user", w)
return
}
refresh := middleware.CreateRefreshToken(uuid)
access := middleware.CreateAccessToken(uuid)
codeReturn := codeReturn{
Access: access,
Refresh: refresh,
}
middleware.WriteJsonOrError(h.logger, codeReturn, w)
}
func (h *AuthHandler) CreateRoutes(r chi.Router) {
h.logger.Info("Mounting auth router")
r.Group(func(r chi.Router) {
r.Use(middleware.SetJson)
r.Post("/login", middleware.WithValidatedPost(h.login))
r.Post("/code", middleware.WithValidatedPost(h.code))
})
}
func CreateAuthHandler(db *sql.DB) AuthHandler {
userModel := models.NewUserModel(db)
logger := log.New(os.Stdout).WithPrefix("Auth")
mailer, err := CreateMailClient(logger)
if err != nil {
panic(err)
}
auth := CreateAuth(mailer)
return AuthHandler{
logger,
userModel,
auth,
}
}