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, } }