Hola, yo resolví el tema de extraer el usuario con base en el func CreatePostHandler(s server.Server) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var req CreatePostRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, "Invalid request body", http.StatusBadRequest) return }
user := services.UserServiceInstance.GetUserFromToken(r, s, w)
post := models.Post{ Title: req.Title, Content: req.Content, UserID: user.Id, }
err := repository.CreatePost(r.Context(), &post) if err != nil { http.Error(w, "Error creating post: "+err.Error(), http.StatusInternalServerError) return }
w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(post) }}usuarioId del Token, de la siguiente forma:
var(ErrUserNotFound= errors.New("user not found"))// UserService contiene la lógica de negocio relacionada con usuariostype UserService struct{}// GetUserFromToken combina las utilidades de JWT con la lógica de negocio// para obtener un usuario completo desde un token en la requestfunc(us *UserService)GetUserFromToken(r *http.Request, s server.Server, w http.ResponseWriter)*models.User{// Usar utilidad para extraer token tokenString,err:= utils.ExtractTokenFromRequest(r)if err != nil { http.Error(w,"Authorization header is required", http.StatusUnauthorized)return nil
}// Usar utilidad para validar token y obtener claims claims,err:= utils.ParseAndValidateToken(tokenString, s.Config().JWTSecret)if err != nil { http.Error(w,"Invalid token: "+err.Error(), http.StatusUnauthorized)return nil
}// Lógica de negocio: obtener usuario de la base de datos user,err:= repository.GetUserById(context.Background(), claims.UserId)if err != nil { http.Error(w,"User not found: "+err.Error(), http.StatusNotFound)return nil
}return user
}// Instancia global del servicio (patrón Singleton simple)varUserServiceInstance=&UserService{}```**auth\_util.go**
```js
var(ErrMissingAuthHeader= errors.New("missing Authorization header")ErrInvalidToken= errors.New("invalid token")ErrInvalidClaims= errors.New("invalid token claims"))// ExtractTokenFromRequest extrae el token JWT del header Authorization de la request// Esta es una función utilitaria pura que solo se encarga de la extracciónfunc ExtractTokenFromRequest(r *http.Request)(string, error){tokenString:= strings.TrimSpace(r.Header.Get("Authorization"))if tokenString ==""{return"",ErrMissingAuthHeader}return tokenString, nil
}// ParseAndValidateToken parsea y valida un token JWT, devolviendo los claims// Esta función es pura y no tiene efectos secundariosfunc ParseAndValidateToken(tokenString string, jwtSecret string)(*models.AppClaims, error){ token,err:= jwt.ParseWithClaims(tokenString,&models.AppClaims{},func(token *jwt.Token)(any, error){return[]byte(jwtSecret), nil
})if err != nil ||!token.Valid{return nil,ErrInvalidToken}if claims,ok:= token.Claims.(*models.AppClaims); ok && token.Valid{return claims, nil
}return nil,ErrInvalidClaims}
Excelente, pensé que no había nadie en éstos cursos por éstos días, conectemos en linkedin:
Debido a que los usuarios normalmente tienen asociadas operaciones de base de datos exclusivas (autenticación, chequeo y hashing de passwords, chequeo de permisos, etc.), preferiría no convertir el UserRepository dentro de una interfaz regular, sino seguir el patrón que utiliza Spring con el CrudRepository y crear uno aparte con las operaciones CRUD generalizadas.
package models
import "time"
type Post struct {
Id string `json:"id"`
PostContent string `json:"post_content"`
CreatedAt time.Time `json:"created_at"`
UserId string `json:"user_id"`
}
Para el caso que se necesite extender la funcionalidad del CRUD, para ciertos modelos solamente, se podría crear varios repositorios adicionales, así sea que cada repositorio tuviese sólo un método ?
Excelente que estés aprendiendo go, pensé que era el único en éstos cursos por éstos días, hagamos conexión por linkedin:
Ojo que en la linea donde esta
json.NewDecoder(r.body).Decode(&postRequest)
no hay validación de que el json sea valido, ya que el metodo decode no hace esa validación.
una forma de tener esa validación es con json.Unmarshal, ya que va a caer en error si es que hay un json invalido.