Files
rideaware-api/internal/auth/handler.go
2025-11-20 19:00:53 -06:00

153 lines
4.5 KiB
Go

package auth
import (
"encoding/json"
"net/http"
"rideaware/internal/config"
"rideaware/internal/user"
)
type Handler struct {
userService *user.Service
}
func NewHandler() *Handler {
return &Handler{
userService: user.NewService(),
}
}
type SignupRequest struct {
Username string `json:"username"`
Password string `json:"password"`
Email string `json:"email"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
type LoginRequest struct {
Username string `json:"username"`
Password string `json:"password"`
}
type TokenResponse struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int `json:"expires_in"`
UserID uint `json:"user_id"`
Username string `json:"username"`
Email string `json:"email"`
}
func (h *Handler) Signup(w http.ResponseWriter, r *http.Request) {
var req SignupRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{"error": "invalid request"})
return
}
newUser, err := h.userService.CreateUser(req.Username, req.Password, req.Email, req.FirstName, req.LastName)
if err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
return
}
accessToken, _ := config.GenerateAccessToken(newUser.ID, newUser.Email, newUser.Username)
refreshToken, _ := config.GenerateRefreshToken(newUser.ID, newUser.Email, newUser.Username)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(TokenResponse{
AccessToken: accessToken,
RefreshToken: refreshToken,
ExpiresIn: 900,
UserID: newUser.ID,
Username: newUser.Username,
Email: newUser.Email,
})
}
func (h *Handler) Login(w http.ResponseWriter, r *http.Request) {
var req LoginRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{"error": "invalid request"})
return
}
user, err := h.userService.VerifyUser(req.Username, req.Password)
if err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusUnauthorized)
json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
return
}
accessToken, _ := config.GenerateAccessToken(user.ID, user.Email, user.Username)
refreshToken, _ := config.GenerateRefreshToken(user.ID, user.Email, user.Username)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(TokenResponse{
AccessToken: accessToken,
RefreshToken: refreshToken,
ExpiresIn: 900,
UserID: user.ID,
Username: user.Username,
Email: user.Email,
})
}
func (h *Handler) RequestPasswordReset(w http.ResponseWriter, r *http.Request) {
var req struct {
Email string `json:"email"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{"error": "invalid request"})
return
}
h.userService.RequestPasswordReset(req.Email)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{
"message": "If email exists, reset link has been sent",
})
}
func (h *Handler) ConfirmPasswordReset(w http.ResponseWriter, r *http.Request) {
var req struct {
Token string `json:"token"`
NewPassword string `json:"new_password"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{"error": "invalid request"})
return
}
if err := h.userService.ResetPassword(req.Token, req.NewPassword); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{
"message": "Password reset successful",
})
}
func (h *Handler) Logout(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"message": "Logout successful"})
}