108 lines
2.3 KiB
Go
108 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) {
|
|
// TODO: validate email
|
|
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()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
auth := CreateAuth(mailer)
|
|
|
|
return AuthHandler{
|
|
logger,
|
|
userModel,
|
|
auth,
|
|
}
|
|
}
|