Para reutilizar los métodos de firmar y decodificar tokens cree un struct que tiene estos métodos. Se inyecta como dependencia en los handlers y middlewares. Por ahora solo contemplo el método HS256 y se puede mejorar para que contemple RS256.
En GetPostById hace falta un elemento importante, que es el de validar que el post con ese id exista. Si se deja tal y como está, se devuelve un 200 con un post con valores por defecto, pero esto es incorrecto, ya que la respuesta correcta debería de ser un 404 Not found.
Esto mismo aplica también a los getters de usuario. Hay algunas funciones especiales que las he creado yo para no tener que ir repitiendo todo el rato el mismo código (como añadir el content-type json)
Para chequear si el post a actualizar existe, sin hacer un SELECT, pueden escribir algo como:
// database/postgres.gofunc(repo *PostgresRepository)UpdatePost(ctx context.Context, post *models.Post)error{ res, err := repo.db.ExecContext(ctx,"UPDATE posts SET post_content = $1 WHERE id = $2 AND user_id = $3", post.PostContent, post.Id, post.UserId)if err !=nil{return err
}// `n` es el numero de filas afectadas. n, err := res.RowsAffected()if err !=nil{return err
}// Si `n` es 0, significa que no actualizamos nadaif n ==0{// Acá pueden retornar cualquier error, // para después controlar qué hacer en handlers/post.goreturn sql.ErrNoRows
}returnnil}// handlers/post.govar PostNotFound = errors.New("post not found")funcUpdatePostHandler(s server.Server) http.HandlerFunc {returnfunc(w http.ResponseWriter, r *http.Request){// ...if err = repository.UpdatePost(r.Context(),&post); err !=nil{// Chequeamos cuál error retornóif errors.Is(err, sql.ErrNoRows){// En este caso, es el error que nosotros elegimos retornar // Entonces, respondemos con http.StatusNotFound helpers.NewResponseError(PostNotFound).Send(w, http.StatusNotFound)}else{// Y en cualquier otro caso, respondemos con http.StatusInternalServerError helpers.NewResponseError(err).Send(w, http.StatusInternalServerError)}return}// Si no hubo error, http.StatusOK helpers.NewResponse(post).Send(w, http.StatusOK)}}
Hay varios aspectos importantes a destacar:
Es fundamental desacoplar los modelos de los controladores. En otras palabras, el controlador/handler debería tener su propia estructura de datos, en lugar de depender directamente del modelo de la base de datos.
También es crucial validar que los recursos solicitados, como un post, realmente pertenezcan al usuario que realiza la solicitud, para garantizar la seguridad y consistencia de la aplicación.
Alguien depronto sabe,
¿Por qué me permite utilizar el endpoint de GET /posts/{id} sin tener token en el header de authorization cuando tengo esta parametrización?
var (
NO_AUTH_NEEDED = []string{
"login",
"signup",
"/",
}
)
Es decir me retorna información en el response sin estar autenticado y sin tener excluída este endpoint en NO_AUTH_NEEDED
Esto es porque pusiste "/" en los NO_AUTH_NEEDED.
Es decir, cuando revisa los paths utilizados, cualquiera que tenga un "/" no va a pedir autenticación... como todas las rutas lo tienen, te deja pasar
Se podría decir que el patrón de Arquitectura que sigue el proyecto es MVC?
En caso afirmativo, El bloque del proyecto encargado de albergar los controladores estaría en los Handlers ??
Alguien podría explicarme por que no es recomendable devolver tanta data en el mismo Request ??
Obviamente por razones de cantidad de información a mostrar, pero depronto hay algun tema de limite de transferencia de infoprmación en un request o algo así?
Estoy pensando meter un CRUD con el stack MERN y que se pueda publicar en el fron una card que se guarde en una collection de mongo db. ¿Como se hace?