diff --git a/go.mod b/go.mod index e2550e7..7c71919 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.9.0 github.com/truemail-rb/truemail-go v1.1.3 + github.com/wwi21seb-projekt/errors-go v0.1.0 golang.org/x/crypto v0.23.0 ) diff --git a/go.sum b/go.sum index 736ddc3..161cdf8 100644 --- a/go.sum +++ b/go.sum @@ -258,6 +258,8 @@ github.com/vanng822/go-premailer v0.0.0-20191214114701-be27abe028fe/go.mod h1:JT github.com/vanng822/go-premailer v1.21.0 h1:qIwX4urphNPO3xa60MGqowmyjzzMtFacJPKNrt1UWFU= github.com/vanng822/go-premailer v1.21.0/go.mod h1:6Y3H2NzNmK3sFBNgR1ENdfV9hzG8hMzrA1nL/XBbbP4= github.com/vanng822/r2router v0.0.0-20150523112421-1023140a4f30/go.mod h1:1BVq8p2jVr55Ost2PkZWDrG86PiJ/0lxqcXoAcGxvWU= +github.com/wwi21seb-projekt/errors-go v0.1.0 h1:JluJstVclUW39zkOa4WiJ5UV2NeqIStae31tm0EQTpA= +github.com/wwi21seb-projekt/errors-go v0.1.0/go.mod h1:PWCPplYjGwrfrp+arG5WmfFA0ElenW/yRwV72iBawcM= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= diff --git a/internal/handlers/post_handler.go b/internal/handlers/post_handler.go index c13eae3..d561321 100644 --- a/internal/handlers/post_handler.go +++ b/internal/handlers/post_handler.go @@ -4,16 +4,18 @@ package handlers import ( "errors" "fmt" - "github.com/gin-gonic/gin" - "github.com/wwi21seb-projekt/server-alpha/internal/managers" - "github.com/wwi21seb-projekt/server-alpha/internal/schemas" - "github.com/wwi21seb-projekt/server-alpha/internal/utils" "net/http" "regexp" "strconv" "strings" "time" + "github.com/gin-gonic/gin" + "github.com/wwi21seb-projekt/errors-go/goerrors" + "github.com/wwi21seb-projekt/server-alpha/internal/managers" + "github.com/wwi21seb-projekt/server-alpha/internal/schemas" + "github.com/wwi21seb-projekt/server-alpha/internal/utils" + "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" @@ -37,6 +39,7 @@ type PostHandler struct { var hashtagRegex = regexp.MustCompile(`#\w+`) var errTransaction = errors.New("error beginning transaction") +var bearerPrefix = "Bearer " // NewPostHandler returns a new PostHandler with the provided managers and validator. func NewPostHandler(databaseManager *managers.DatabaseMgr, jwtManager *managers.JWTMgr) PostHdl { @@ -53,7 +56,7 @@ func (handler *PostHandler) CreatePost(ctx *gin.Context) { // Begin a new transaction tx := utils.BeginTransaction(ctx, handler.DatabaseManager.GetPool()) if tx == nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, errTransaction) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, errTransaction) return } var err error @@ -89,7 +92,7 @@ func (handler *PostHandler) CreatePost(ctx *gin.Context) { _, err = tx.Exec(ctx, queryString, queryArgs...) if err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } @@ -103,13 +106,13 @@ func (handler *PostHandler) CreatePost(ctx *gin.Context) { ON CONFLICT (content) DO UPDATE SET content=alpha_schema.hashtags.content RETURNING hashtag_id` if err := tx.QueryRow(ctx, queryString, hashtagId, hashtag).Scan(&hashtagId); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } queryString = "INSERT INTO alpha_schema.many_posts_has_many_hashtags (post_id_posts, hashtag_id_hashtags) VALUES($1, $2)" if _, err = tx.Exec(ctx, queryString, postId, hashtagId); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } } @@ -120,7 +123,7 @@ func (handler *PostHandler) CreatePost(ctx *gin.Context) { author := &schemas.AuthorDTO{} if err := row.Scan(&author.Username, &author.Nickname); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } @@ -155,7 +158,7 @@ func (handler *PostHandler) DeletePost(ctx *gin.Context) { // Begin a new transaction tx := utils.BeginTransaction(ctx, handler.DatabaseManager.GetPool()) if tx == nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, errTransaction) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, errTransaction) return } var err error @@ -174,17 +177,17 @@ func (handler *PostHandler) DeletePost(ctx *gin.Context) { var content string if err := row.Scan(&authorId, &content); err != nil { if errors.Is(err, pgx.ErrNoRows) { - utils.WriteAndLogError(ctx, schemas.PostNotFound, http.StatusNotFound, err) + utils.WriteAndLogError(ctx, goerrors.PostNotFound, http.StatusNotFound, err) return } - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } userId := claims["sub"].(string) if userId != authorId { - utils.WriteAndLogError(ctx, schemas.DeletePostForbidden, http.StatusForbidden, + utils.WriteAndLogError(ctx, goerrors.DeletePostForbidden, http.StatusForbidden, errors.New("user is not the author of the post")) return } @@ -192,7 +195,7 @@ func (handler *PostHandler) DeletePost(ctx *gin.Context) { // Delete the post queryString = "DELETE FROM alpha_schema.posts WHERE post_id = $1" if _, err = tx.Exec(ctx, queryString, postId); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } @@ -206,7 +209,7 @@ func (handler *PostHandler) DeletePost(ctx *gin.Context) { for _, hashtag := range hashtags { if _, err = tx.Exec(ctx, queryString, hashtag); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } } @@ -225,7 +228,7 @@ func (handler *PostHandler) DeletePost(ctx *gin.Context) { func (handler *PostHandler) QueryPosts(ctx *gin.Context) { tx := utils.BeginTransaction(ctx, handler.DatabaseManager.GetPool()) if tx == nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, errTransaction) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, errTransaction) return } var err error @@ -274,7 +277,7 @@ func (handler *PostHandler) QueryPosts(ctx *gin.Context) { paginatedResponse := createPaginatedResponse(posts, lastPostId, limit, count) if err := utils.CommitTransaction(ctx, tx); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) } utils.WriteAndLogResponse(ctx, paginatedResponse, http.StatusOK) @@ -286,7 +289,7 @@ func (handler *PostHandler) HandleGetFeedRequest(ctx *gin.Context) { // Begin a new transaction tx := utils.BeginTransaction(ctx, handler.DatabaseManager.GetPool()) if tx == nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, errTransaction) return } @@ -308,7 +311,7 @@ func (handler *PostHandler) HandleGetFeedRequest(ctx *gin.Context) { paginatedResponse := createPaginatedResponse(posts, lastPostId, limit, records) if err := utils.CommitTransaction(ctx, tx); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) } utils.WriteAndLogResponse(ctx, paginatedResponse, http.StatusOK) @@ -347,16 +350,16 @@ func determineFeedType(c *gin.Context, handler *PostHandler) (bool, jwt.Claims, if authHeader == "" { publicFeedWanted = true } else { - if !strings.HasPrefix(authHeader, "Bearer ") || len(authHeader) <= len("Bearer ") { + if !strings.HasPrefix(authHeader, bearerPrefix) || len(authHeader) <= len(bearerPrefix) { err = errors.New("invalid authorization header") - utils.WriteAndLogError(c, schemas.InvalidToken, http.StatusBadRequest, err) + utils.WriteAndLogError(c, goerrors.InvalidToken, http.StatusBadRequest, err) return false, nil, err } - jwtToken := authHeader[len("Bearer "):] + jwtToken := authHeader[len(bearerPrefix):] claims, err = handler.JWTManager.ValidateJWT(jwtToken) if err != nil { - utils.WriteAndLogError(c, schemas.Unauthorized, http.StatusUnauthorized, err) + utils.WriteAndLogError(c, goerrors.Unauthorized, http.StatusUnauthorized, err) return false, nil, err } @@ -435,13 +438,13 @@ func retrieveFeed(ctx *gin.Context, tx pgx.Tx, publicFeedWanted bool, // RetrieveCountAndRecords retrieves the count of posts that match the criteria and the corresponding post records. // It executes the provided count and data queries, processes the results, and returns the post count along with the post DTOs. func retrieveCountAndRecords(ctx *gin.Context, tx pgx.Tx, countQuery string, countQueryArgs []interface{}, - dataQuery string, dataQueryArgs []interface{}) (int, []*schemas.PostDTO, *schemas.CustomError, int, error) { + dataQuery string, dataQueryArgs []interface{}) (int, []*schemas.PostDTO, *goerrors.CustomError, int, error) { // Get the count of posts in the database that match the criteria row := tx.QueryRow(ctx, countQuery, countQueryArgs...) var count int if err := row.Scan(&count); err != nil { - return 0, nil, schemas.DatabaseError, http.StatusInternalServerError, err + return 0, nil, goerrors.DatabaseError, http.StatusInternalServerError, err } var rows pgx.Rows @@ -449,7 +452,7 @@ func retrieveCountAndRecords(ctx *gin.Context, tx pgx.Tx, countQuery string, cou rows, err = tx.Query(ctx, dataQuery, dataQueryArgs...) if err != nil { - return 0, nil, schemas.DatabaseError, http.StatusInternalServerError, err + return 0, nil, goerrors.DatabaseError, http.StatusInternalServerError, err } // Iterate over the rows and create the post DTOs @@ -463,7 +466,7 @@ func retrieveCountAndRecords(ctx *gin.Context, tx pgx.Tx, countQuery string, cou if err := rows.Scan(&post.PostId, &post.Author.Username, &post.Author.Nickname, &post.Author.ProfilePictureURL, &post.Content, &createdAt, &longitude, &latitude, &accuracy); err != nil { - return 0, nil, schemas.DatabaseError, http.StatusInternalServerError, err + return 0, nil, goerrors.DatabaseError, http.StatusInternalServerError, err } if longitude.Valid && latitude.Valid { diff --git a/internal/handlers/subscription_handler.go b/internal/handlers/subscription_handler.go index 2015ee3..d167025 100644 --- a/internal/handlers/subscription_handler.go +++ b/internal/handlers/subscription_handler.go @@ -3,12 +3,14 @@ package handlers import ( "errors" "fmt" + "net/http" + "time" + "github.com/gin-gonic/gin" + "github.com/wwi21seb-projekt/errors-go/goerrors" "github.com/wwi21seb-projekt/server-alpha/internal/managers" "github.com/wwi21seb-projekt/server-alpha/internal/schemas" "github.com/wwi21seb-projekt/server-alpha/internal/utils" - "net/http" - "time" "github.com/golang-jwt/jwt/v5" "github.com/google/uuid" @@ -45,7 +47,7 @@ func (handler *SubscriptionHandler) HandleGetSubscriptions(ctx *gin.Context) { // Get pagination parameters offset, limit, err := utils.ParsePaginationParams(ctx) if err != nil { - utils.WriteAndLogError(ctx, schemas.BadRequest, http.StatusBadRequest, err) + utils.WriteAndLogError(ctx, goerrors.BadRequest, http.StatusBadRequest, err) return } @@ -63,11 +65,11 @@ func (handler *SubscriptionHandler) HandleGetSubscriptions(ctx *gin.Context) { findUserQuery := "SELECT user_id FROM alpha_schema.users WHERE username = $1" rows, err := handler.DatabaseManager.GetPool().Query(ctx, findUserQuery, username) if err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } if !rows.Next() { - utils.WriteAndLogError(ctx, schemas.UserNotFound, http.StatusNotFound, errors.New("user not found")) + utils.WriteAndLogError(ctx, goerrors.UserNotFound, http.StatusNotFound, errors.New("user not found")) return } @@ -91,7 +93,7 @@ func (handler *SubscriptionHandler) HandleGetSubscriptions(ctx *gin.Context) { rows, err = handler.DatabaseManager.GetPool().Query(ctx, subscriptionQuery, jwtUserId, username) if err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } @@ -102,7 +104,7 @@ func (handler *SubscriptionHandler) HandleGetSubscriptions(ctx *gin.Context) { followerId, followingId := uuid.UUID{}, uuid.UUID{} if err := rows.Scan(&followingId, &followerId, &subscription.Username, &subscription.Nickname, &subscription.ProfilePictureUrl); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } @@ -121,7 +123,7 @@ func (handler *SubscriptionHandler) HandleGetSubscriptions(ctx *gin.Context) { row := handler.DatabaseManager.GetPool().QueryRow(ctx, countQuery, username) var totalSubscriptions int if err := row.Scan(&totalSubscriptions); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } @@ -150,11 +152,11 @@ func (handler *SubscriptionHandler) Subscribe(ctx *gin.Context) { var subscribeeId string if err = row.Scan(&subscribeeId); err != nil { if errors.Is(err, pgx.ErrNoRows) { - utils.WriteAndLogError(ctx, schemas.UserNotFound, http.StatusNotFound, err) + utils.WriteAndLogError(ctx, goerrors.UserNotFound, http.StatusNotFound, err) return } - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } @@ -165,7 +167,7 @@ func (handler *SubscriptionHandler) Subscribe(ctx *gin.Context) { // Check and throw error if the user wants to subscribe to himself if jwtUserId == subscribeeId { - utils.WriteAndLogError(ctx, schemas.SubscriptionSelfFollow, http.StatusNotAcceptable, + utils.WriteAndLogError(ctx, goerrors.SubscriptionSelfFollow, http.StatusNotAcceptable, errors.New("user cannot subscribe to himself")) return } @@ -177,14 +179,14 @@ func (handler *SubscriptionHandler) Subscribe(ctx *gin.Context) { if err := rows.Scan(&subscriptionId); err != nil { if !errors.Is(err, pgx.ErrNoRows) { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } } if subscriptionId != uuid.Nil { // User is already subscribed, since the subscriptionId is not nil - utils.WriteAndLogError(ctx, schemas.SubscriptionAlreadyExists, http.StatusConflict, + utils.WriteAndLogError(ctx, goerrors.SubscriptionAlreadyExists, http.StatusConflict, errors.New("subscription already exists")) return } @@ -195,7 +197,7 @@ func (handler *SubscriptionHandler) Subscribe(ctx *gin.Context) { createdAt := time.Now() if _, err := tx.Exec(ctx, queryString, subscriptionId, jwtUserId, subscribeeId, createdAt); err != nil { log.Errorf("error while inserting subscription: %v", err) - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } @@ -240,17 +242,17 @@ func (handler *SubscriptionHandler) Unsubscribe(ctx *gin.Context) { var subscriberId, subscribeeId string if err := row.Scan(&subscriberId, &subscribeeId); err != nil { if errors.Is(err, pgx.ErrNoRows) { - utils.WriteAndLogError(ctx, schemas.SubscriptionNotFound, http.StatusNotFound, + utils.WriteAndLogError(ctx, goerrors.SubscriptionNotFound, http.StatusNotFound, errors.New("subscription not found")) return } - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } // Check and throw error if user wants to delete someone else's subscription if subscriberId != jwtUserId { - utils.WriteAndLogError(ctx, schemas.UnsubscribeForbidden, http.StatusForbidden, + utils.WriteAndLogError(ctx, goerrors.UnsubscribeForbidden, http.StatusForbidden, errors.New("you can only delete your own subscriptions")) return } @@ -259,11 +261,11 @@ func (handler *SubscriptionHandler) Unsubscribe(ctx *gin.Context) { queryString = "DELETE FROM alpha_schema.subscriptions WHERE subscription_id = $1" if _, err := tx.Exec(ctx, queryString, subscriptionId); err != nil { if errors.Is(err, pgx.ErrNoRows) { - utils.WriteAndLogError(ctx, schemas.SubscriptionNotFound, http.StatusNotFound, + utils.WriteAndLogError(ctx, goerrors.SubscriptionNotFound, http.StatusNotFound, errors.New("subscription not found")) return } - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } diff --git a/internal/handlers/user_handler.go b/internal/handlers/user_handler.go index 3a009d0..50e6433 100644 --- a/internal/handlers/user_handler.go +++ b/internal/handlers/user_handler.go @@ -2,18 +2,20 @@ package handlers import ( "errors" - "github.com/gin-gonic/gin" "math/rand" "net/http" "strconv" "time" + "github.com/gin-gonic/gin" + "github.com/golang-jwt/jwt/v5" "github.com/google/uuid" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" "golang.org/x/crypto/bcrypt" + "github.com/wwi21seb-projekt/errors-go/goerrors" "github.com/wwi21seb-projekt/server-alpha/internal/managers" "github.com/wwi21seb-projekt/server-alpha/internal/schemas" "github.com/wwi21seb-projekt/server-alpha/internal/utils" @@ -80,7 +82,7 @@ func (handler *UserHandler) RegisterUser(ctx *gin.Context) { hashedPassword, err := bcrypt.GenerateFromPassword([]byte(registrationRequest.Password), bcrypt.DefaultCost) if err != nil { - utils.WriteAndLogError(ctx, schemas.InternalServerError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.InternalServerError, http.StatusInternalServerError, err) return } @@ -91,7 +93,7 @@ func (handler *UserHandler) RegisterUser(ctx *gin.Context) { queryString := "INSERT INTO alpha_schema.users (user_id, username, nickname, email, password, created_at, expires_at, status, profile_picture_url) VALUES ($1, $2, $3, $4, $5, $6, $7,$8,$9)" if _, err = tx.Exec(ctx, queryString, userId, registrationRequest.Username, registrationRequest.Nickname, registrationRequest.Email, hashedPassword, createdAt, expiresAt, "", ""); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } @@ -143,7 +145,7 @@ func (handler *UserHandler) ActivateUser(ctx *gin.Context) { if _, activated, err := checkUserExistenceAndActivation(ctx, tx, username); err != nil { return } else if activated { - utils.WriteAndLogError(ctx, schemas.UserAlreadyActivated, http.StatusAlreadyReported, errors.New("already activated")) + utils.WriteAndLogError(ctx, goerrors.UserAlreadyActivated, http.StatusAlreadyReported, errors.New("already activated")) return } @@ -155,21 +157,21 @@ func (handler *UserHandler) ActivateUser(ctx *gin.Context) { // Activate the user queryString := "UPDATE alpha_schema.users SET activated_at = $1 WHERE user_id = $2" if _, err := tx.Exec(ctx, queryString, time.Now(), userID); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } // Delete the token queryString = "DELETE FROM alpha_schema.activation_tokens WHERE token = $1" if _, err := tx.Exec(ctx, queryString, activationRequest.Token); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } // Generate token pair tokenDto, err := generateTokenPair(handler, userID.String(), username) if err != nil { - utils.WriteAndLogError(ctx, schemas.InternalServerError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.InternalServerError, http.StatusInternalServerError, err) return } @@ -203,7 +205,7 @@ func (handler *UserHandler) ResendToken(ctx *gin.Context) { if _, activated, err := checkUserExistenceAndActivation(ctx, tx, username); err != nil { return } else if activated { - utils.WriteAndLogError(ctx, schemas.UserAlreadyActivated, http.StatusAlreadyReported, + utils.WriteAndLogError(ctx, goerrors.UserAlreadyActivated, http.StatusAlreadyReported, errors.New("already activated")) return } @@ -238,7 +240,7 @@ func (handler *UserHandler) ChangeTrivialInformation(ctx *gin.Context) { // Get the user ID from the JWT token claims, ok := ctx.Value(utils.ClaimsKey.String()).(jwt.MapClaims) if !ok { - utils.WriteAndLogError(ctx, schemas.Unauthorized, http.StatusUnauthorized, + utils.WriteAndLogError(ctx, goerrors.Unauthorized, http.StatusUnauthorized, errors.New("unauthorized")) return } @@ -247,7 +249,7 @@ func (handler *UserHandler) ChangeTrivialInformation(ctx *gin.Context) { // Change the user's nickname and status queryString := "UPDATE alpha_schema.users SET nickname = $1, status = $2 WHERE user_id = $3" if _, err := tx.Exec(ctx, queryString, changeTrivialInformationRequest.NewNickname, changeTrivialInformationRequest.Status, userId); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } @@ -281,7 +283,7 @@ func (handler *UserHandler) ChangePassword(ctx *gin.Context) { // Get the user ID from the JWT token claims, ok := ctx.Value(utils.ClaimsKey.String()).(jwt.MapClaims) if !ok { - utils.WriteAndLogError(ctx, schemas.Unauthorized, http.StatusUnauthorized, errors.New("unauthorized")) + utils.WriteAndLogError(ctx, goerrors.Unauthorized, http.StatusUnauthorized, errors.New("unauthorized")) return } username := claims["username"].(string) @@ -295,14 +297,14 @@ func (handler *UserHandler) ChangePassword(ctx *gin.Context) { // Hash the new password hashedPassword, err := bcrypt.GenerateFromPassword([]byte(passwordChangeRequest.NewPassword), bcrypt.DefaultCost) if err != nil { - utils.WriteAndLogError(ctx, schemas.InternalServerError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.InternalServerError, http.StatusInternalServerError, err) return } // Update the user's password in the database queryString := "UPDATE alpha_schema.users SET password = $1 WHERE user_id = $2" if _, err = tx.Exec(ctx, queryString, hashedPassword, userId); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } @@ -336,12 +338,12 @@ func (handler *UserHandler) LoginUser(ctx *gin.Context) { } if !exists { - utils.WriteAndLogError(ctx, schemas.InvalidCredentials, 404, errors.New("username does not exist")) + utils.WriteAndLogError(ctx, goerrors.InvalidCredentials, 404, errors.New("username does not exist")) return } if !activated { - utils.WriteAndLogError(ctx, schemas.UserNotActivated, 403, errors.New("user not activated")) + utils.WriteAndLogError(ctx, goerrors.UserNotActivated, 403, errors.New("user not activated")) return } @@ -359,7 +361,7 @@ func (handler *UserHandler) LoginUser(ctx *gin.Context) { // Generate token pair tokenDto, err := generateTokenPair(handler, userId.String(), loginRequest.Username) if err != nil { - utils.WriteAndLogError(ctx, schemas.InternalServerError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.InternalServerError, http.StatusInternalServerError, err) return } @@ -386,7 +388,7 @@ func (handler *UserHandler) HandleGetUserRequest(ctx *gin.Context) { row := handler.DatabaseManager.GetPool().QueryRow(ctx, queryString, username) if err := row.Scan(&userId, &user.Username, &user.Nickname, &user.Status, &user.ProfilePicture); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } @@ -394,7 +396,7 @@ func (handler *UserHandler) HandleGetUserRequest(ctx *gin.Context) { queryString = "SELECT COUNT(*) FROM alpha_schema.posts WHERE author_id = $1" row = handler.DatabaseManager.GetPool().QueryRow(ctx, queryString, userId) if err := row.Scan(&user.Posts); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } @@ -402,7 +404,7 @@ func (handler *UserHandler) HandleGetUserRequest(ctx *gin.Context) { queryString = "SELECT COUNT(*) FROM alpha_schema.subscriptions WHERE subscribee_id = $1" row = handler.DatabaseManager.GetPool().QueryRow(ctx, queryString, userId) if err := row.Scan(&user.Follower); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } @@ -410,7 +412,7 @@ func (handler *UserHandler) HandleGetUserRequest(ctx *gin.Context) { queryString = "SELECT COUNT(*) FROM alpha_schema.subscriptions WHERE subscriber_id = $1" row = handler.DatabaseManager.GetPool().QueryRow(ctx, queryString, userId) if err := row.Scan(&user.Following); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } @@ -435,7 +437,7 @@ func (handler *UserHandler) SearchUsers(ctx *gin.Context) { searchQuery := ctx.Query(utils.UsernameParamKey) offset, limit, err := utils.ParsePaginationParams(ctx) if err != nil { - utils.WriteAndLogError(ctx, schemas.BadRequest, http.StatusBadRequest, err) + utils.WriteAndLogError(ctx, goerrors.BadRequest, http.StatusBadRequest, err) return } @@ -443,7 +445,7 @@ func (handler *UserHandler) SearchUsers(ctx *gin.Context) { queryString := "SELECT username, nickname, profile_picture_url, levenshtein(username, $1) as ld FROM alpha_schema.users WHERE levenshtein(username, $1) <= 5 ORDER BY ld" rows, err := handler.DatabaseManager.GetPool().Query(ctx, queryString, searchQuery) if err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } defer rows.Close() @@ -454,7 +456,7 @@ func (handler *UserHandler) SearchUsers(ctx *gin.Context) { for rows.Next() { user := schemas.AuthorDTO{} if err := rows.Scan(&user.Username, &user.Nickname, &user.ProfilePictureURL, &ld); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } users = append(users, user) @@ -472,7 +474,7 @@ func (handler *UserHandler) RefreshToken(ctx *gin.Context) { // Get the user ID and username from the refresh token refreshTokenClaims, err := handler.JWTManager.ValidateJWT(refreshTokenRequest.RefreshToken) if err != nil { - utils.WriteAndLogError(ctx, schemas.InvalidToken, http.StatusUnauthorized, err) + utils.WriteAndLogError(ctx, goerrors.InvalidToken, http.StatusUnauthorized, err) return } @@ -482,14 +484,14 @@ func (handler *UserHandler) RefreshToken(ctx *gin.Context) { isRefreshToken := refreshClaims["refresh"].(string) if isRefreshToken != "true" { - utils.WriteAndLogError(ctx, schemas.Unauthorized, http.StatusUnauthorized, errInvalidToken) + utils.WriteAndLogError(ctx, goerrors.Unauthorized, http.StatusUnauthorized, errInvalidToken) return } // Generate token pair tokenDto, err := generateTokenPair(handler, userId, username) if err != nil { - utils.WriteAndLogError(ctx, schemas.InternalServerError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.InternalServerError, http.StatusInternalServerError, err) return } @@ -503,7 +505,7 @@ func retrieveUserIdAndEmail(ctx *gin.Context, tx pgx.Tx, username string) (strin queryString := "SELECT email, user_id FROM alpha_schema.users WHERE username = $1" rows, err := tx.Query(ctx, queryString, username) if err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return "", uuid.UUID{}, true } defer rows.Close() @@ -512,11 +514,11 @@ func retrieveUserIdAndEmail(ctx *gin.Context, tx pgx.Tx, username string) (strin var userID uuid.UUID if rows.Next() { if err := rows.Scan(&email, &userID); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return "", uuid.UUID{}, true } } else { - utils.WriteAndLogError(ctx, schemas.UserNotFound, http.StatusNotFound, errors.New("user not found")) + utils.WriteAndLogError(ctx, goerrors.UserNotFound, http.StatusNotFound, errors.New("user not found")) return "", uuid.UUID{}, true } @@ -528,7 +530,7 @@ func checkUsernameEmailTaken(ctx *gin.Context, tx pgx.Tx, username, email string queryString := "SELECT username, email FROM alpha_schema.users WHERE username = $1 OR email = $2" rows, err := tx.Query(ctx, queryString, username, email) if err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return err } defer rows.Close() @@ -538,15 +540,15 @@ func checkUsernameEmailTaken(ctx *gin.Context, tx pgx.Tx, username, email string var foundEmail string if err := rows.Scan(&foundUsername, &foundEmail); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return err } - customErr := &schemas.CustomError{} + customErr := &goerrors.CustomError{} if foundUsername == username { - customErr = schemas.UsernameTaken + customErr = goerrors.UsernameTaken } else { - customErr = schemas.EmailTaken + customErr = goerrors.EmailTaken } err = errors.New("username or email taken") @@ -562,24 +564,24 @@ func checkTokenValidity(ctx *gin.Context, tx pgx.Tx, token, username string) err queryString := "SELECT expires_at FROM alpha_schema.activation_tokens WHERE token = $1 AND user_id = (SELECT user_id FROM alpha_schema.users WHERE username = $2)" rows, err := tx.Query(ctx, queryString, token, username) if err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return err } defer rows.Close() if !rows.Next() { - utils.WriteAndLogError(ctx, schemas.InvalidToken, http.StatusUnauthorized, errInvalidToken) + utils.WriteAndLogError(ctx, goerrors.InvalidToken, http.StatusUnauthorized, errInvalidToken) return errInvalidToken } var expiresAt pgtype.Timestamptz if err := rows.Scan(&expiresAt); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return err } if time.Now().After(expiresAt.Time) { - utils.WriteAndLogError(ctx, schemas.ActivationTokenExpired, http.StatusUnauthorized, + utils.WriteAndLogError(ctx, goerrors.ActivationTokenExpired, http.StatusUnauthorized, errors.New("token expired")) return errors.New("token expired") } @@ -592,7 +594,7 @@ func checkUserExistenceAndActivation(ctx *gin.Context, tx pgx.Tx, username strin queryString := "SELECT activated_at FROM alpha_schema.users WHERE username = $1" rows, err := tx.Query(ctx, queryString, username) if err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return false, false, err } defer rows.Close() @@ -600,7 +602,7 @@ func checkUserExistenceAndActivation(ctx *gin.Context, tx pgx.Tx, username strin var activatedAt pgtype.Timestamptz if rows.Next() { if err := rows.Scan(&activatedAt); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return false, false, err } } else { @@ -620,19 +622,19 @@ func (handler *UserHandler) generateAndSendToken(ctx *gin.Context, tx pgx.Tx, em // Delete the old token if it exists queryString := "DELETE FROM alpha_schema.activation_tokens WHERE user_id = $1" if _, err := tx.Exec(ctx, queryString, userId); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return err } queryString = "INSERT INTO alpha_schema.activation_tokens (token_id, user_id, token, expires_at) VALUES ($1, $2, $3, $4)" if _, err := tx.Exec(ctx, queryString, tokenID, userId, token, tokenExpiresAt); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return err } // Send the token to the user if err := handler.MailManager.SendActivationMail(email, username, token, "UI-Service"); err != nil { - utils.WriteAndLogError(ctx, schemas.EmailNotSent, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.EmailNotSent, http.StatusInternalServerError, err) return err } @@ -652,7 +654,7 @@ func checkPassword(ctx *gin.Context, tx pgx.Tx, username, givenPassword string) queryString := "SELECT password, user_id FROM alpha_schema.users WHERE username = $1" rows, err := tx.Query(ctx, queryString, username) if err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return err } defer rows.Close() @@ -662,12 +664,12 @@ func checkPassword(ctx *gin.Context, tx pgx.Tx, username, givenPassword string) rows.Next() // We already asserted existence earlier, so we can assume that the row exists if err := rows.Scan(&password, &userId); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return err } if err := bcrypt.CompareHashAndPassword([]byte(password), []byte(givenPassword)); err != nil { - utils.WriteAndLogError(ctx, schemas.InvalidCredentials, http.StatusForbidden, err) + utils.WriteAndLogError(ctx, goerrors.InvalidCredentials, http.StatusForbidden, err) return err } return nil @@ -700,7 +702,7 @@ func (handler *UserHandler) RetrieveUserPosts(ctx *gin.Context) { offset, limit, err := utils.ParsePaginationParams(ctx) if err != nil { - utils.WriteAndLogError(ctx, schemas.BadRequest, http.StatusBadRequest, err) + utils.WriteAndLogError(ctx, goerrors.BadRequest, http.StatusBadRequest, err) return } @@ -710,7 +712,7 @@ func (handler *UserHandler) RetrieveUserPosts(ctx *gin.Context) { "WHERE u.username = $1 ORDER BY p.created_at DESC" rows, err := handler.DatabaseManager.GetPool().Query(ctx, queryString, username) if err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } defer rows.Close() @@ -724,7 +726,7 @@ func (handler *UserHandler) RetrieveUserPosts(ctx *gin.Context) { for rows.Next() { post := schemas.PostDTO{} if err := rows.Scan(&post.PostId, &post.Content, &createdAt, &longitude, &latitude, &accuracy); err != nil { - utils.WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + utils.WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return } diff --git a/internal/initializer.go b/internal/initializer.go index 0955f86..29df00a 100644 --- a/internal/initializer.go +++ b/internal/initializer.go @@ -4,14 +4,15 @@ package internal import ( "context" "fmt" - log "github.com/sirupsen/logrus" - "github.com/wwi21seb-projekt/server-alpha/internal/managers" - "github.com/wwi21seb-projekt/server-alpha/internal/utils" "net/http" "os" "os/signal" "time" + log "github.com/sirupsen/logrus" + "github.com/wwi21seb-projekt/server-alpha/internal/managers" + "github.com/wwi21seb-projekt/server-alpha/internal/utils" + "github.com/jackc/pgx/v5/pgxpool" "github.com/joho/godotenv" "github.com/wwi21seb-projekt/server-alpha/internal/routing" diff --git a/internal/managers/jwt_manager.go b/internal/managers/jwt_manager.go index 976999c..b9a0613 100644 --- a/internal/managers/jwt_manager.go +++ b/internal/managers/jwt_manager.go @@ -8,12 +8,14 @@ import ( "encoding/pem" "errors" "fmt" - "github.com/wwi21seb-projekt/server-alpha/internal/schemas" - "github.com/wwi21seb-projekt/server-alpha/internal/utils" "net/http" "os" "time" + "github.com/wwi21seb-projekt/errors-go/goerrors" + "github.com/wwi21seb-projekt/server-alpha/internal/schemas" + "github.com/wwi21seb-projekt/server-alpha/internal/utils" + "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" log "github.com/sirupsen/logrus" @@ -82,14 +84,14 @@ func (jm *JWTManager) JWTMiddleware() gin.HandlerFunc { return func(c *gin.Context) { authHeader := c.GetHeader("Authorization") if authHeader == "" { - c.AbortWithStatusJSON(http.StatusUnauthorized, &schemas.ErrorDTO{Error: *schemas.Unauthorized}) + c.AbortWithStatusJSON(http.StatusUnauthorized, &schemas.ErrorDTO{Error: *goerrors.Unauthorized}) return } // Validate the JWT token token := authHeader[len("Bearer "):] claims, err := jm.ValidateJWT(token) if err != nil || claims.(jwt.MapClaims)["refresh"] == "true" { - c.AbortWithStatusJSON(http.StatusUnauthorized, &schemas.ErrorDTO{Error: *schemas.Unauthorized}) + c.AbortWithStatusJSON(http.StatusUnauthorized, &schemas.ErrorDTO{Error: *goerrors.Unauthorized}) return } // Add the claims to the request context diff --git a/internal/middleware/validation.go b/internal/middleware/validation.go index e9e8c92..de5a29d 100644 --- a/internal/middleware/validation.go +++ b/internal/middleware/validation.go @@ -1,10 +1,12 @@ package middleware import ( + "net/http" + + "github.com/wwi21seb-projekt/errors-go/goerrors" "github.com/wwi21seb-projekt/server-alpha/internal/schemas" "github.com/wwi21seb-projekt/server-alpha/internal/utils" "github.com/wwi21seb-projekt/server-alpha/internal/validators" - "net/http" "github.com/gin-gonic/gin" ) @@ -12,19 +14,19 @@ import ( func ValidateAndSanitizeStruct(obj interface{}) gin.HandlerFunc { return func(c *gin.Context) { if err := c.ShouldBindJSON(obj); err != nil { - c.AbortWithStatusJSON(http.StatusBadRequest, &schemas.ErrorDTO{Error: *schemas.BadRequest}) + c.AbortWithStatusJSON(http.StatusBadRequest, &schemas.ErrorDTO{Error: *goerrors.BadRequest}) return } validator := validators.GetValidator() // Sanitize the data if err := validator.SanitizeData(obj); err != nil { - c.AbortWithStatusJSON(http.StatusBadRequest, &schemas.ErrorDTO{Error: *schemas.BadRequest}) + c.AbortWithStatusJSON(http.StatusBadRequest, &schemas.ErrorDTO{Error: *goerrors.BadRequest}) return } if err := validator.Validate.Struct(obj); err != nil { // Handle validation errors as before - c.AbortWithStatusJSON(http.StatusBadRequest, &schemas.ErrorDTO{Error: *schemas.BadRequest}) + c.AbortWithStatusJSON(http.StatusBadRequest, &schemas.ErrorDTO{Error: *goerrors.BadRequest}) return } // Set the sanitized object in the context diff --git a/internal/schemas/dtos.go b/internal/schemas/dtos.go index 2af0c3f..5c63256 100644 --- a/internal/schemas/dtos.go +++ b/internal/schemas/dtos.go @@ -1,11 +1,14 @@ package schemas -import "github.com/google/uuid" +import ( + "github.com/google/uuid" + "github.com/wwi21seb-projekt/errors-go/goerrors" +) // ErrorDTO is a struct that represents an error response // Error is the custom error, see CustomError type ErrorDTO struct { - Error CustomError `json:"error"` + Error goerrors.CustomError `json:"error"` } // ImprintDTO is a struct that represents an imprint response diff --git a/internal/schemas/errors.go b/internal/schemas/errors.go deleted file mode 100644 index fab042b..0000000 --- a/internal/schemas/errors.go +++ /dev/null @@ -1,92 +0,0 @@ -package schemas - -// CustomError is a struct that represents a custom error -// Message is the error message -// Code is the error code -type CustomError struct { - Message string `json:"message"` - Code string `json:"code"` -} - -var ( - BadRequest = &CustomError{ - Message: "The request body is invalid. Please check the request body and try again.", - Code: "ERR-001", - } - UsernameTaken = &CustomError{ - Message: "The username is already taken. Please try another username.", - Code: "ERR-002", - } - EmailTaken = &CustomError{ - Message: "The email is already taken. Please try another email.", - Code: "ERR-003", - } - UserNotFound = &CustomError{ - Message: "The user was not found. Please check the username and try again.", - Code: "ERR-004", - } - UserNotActivated = &CustomError{ - Message: "The user is not activated. Please activate the user and try again.", - Code: "ERR-005", - } - ActivationTokenExpired = &CustomError{ - Message: "The token has expired. Please check your mail for a new token and try again.", - Code: "ERR-006", - } - InvalidToken = &CustomError{ - Message: "The token is invalid. Please check the token and try again.", - Code: "ERR-007", - } - InvalidCredentials = &CustomError{ - Message: "The credentials are invalid. Please check the credentials and try again.", - Code: "ERR-008", - } - InternalServerError = &CustomError{ - Message: "An internal server error occurred. Please try again later.", - Code: "ERR-009", - } - DatabaseError = &CustomError{ - Message: "A database error occurred. Please try again later.", - Code: "ERR-010", - } - EmailUnreachable = &CustomError{ - Message: "The email is unreachable. Please check the email and try again.", - Code: "ERR-011", - } - EmailNotSent = &CustomError{ - Message: "The email could not be sent. Please try again later.", - Code: "ERR-012", - } - UserAlreadyActivated = &CustomError{ - Message: "The user is already activated. Please login to your account.", - Code: "ERR-013", - } - Unauthorized = &CustomError{ - Message: "The request is unauthorized. Please login to your account.", - Code: "ERR-014", - } - SubscriptionNotFound = &CustomError{ - Message: "The subscription was not found. Please check the username and try again.", - Code: "ERR-015", - } - SubscriptionAlreadyExists = &CustomError{ - Message: "The subscription already exists. Please check the username and try again.", - Code: "ERR-016", - } - SubscriptionSelfFollow = &CustomError{ - Message: "You cannot follow yourself. Please check the username and try again.", - Code: "ERR-017", - } - UnsubscribeForbidden = &CustomError{ - Message: "You can only delete your own subscriptions.", - Code: "ERR-018", - } - DeletePostForbidden = &CustomError{ - Message: "You can only delete your own posts.", - Code: "ERR-019", - } - PostNotFound = &CustomError{ - Message: "The post was not found. Please check the post ID and try again.", - Code: "ERR-020", - } -) diff --git a/internal/utils/pagination.go b/internal/utils/pagination.go index 26ed9b4..77ac3c2 100644 --- a/internal/utils/pagination.go +++ b/internal/utils/pagination.go @@ -3,11 +3,13 @@ package utils import ( "errors" - "github.com/gin-gonic/gin" - "github.com/wwi21seb-projekt/server-alpha/internal/schemas" "net/http" "reflect" "strconv" + + "github.com/gin-gonic/gin" + "github.com/wwi21seb-projekt/errors-go/goerrors" + "github.com/wwi21seb-projekt/server-alpha/internal/schemas" ) // ParsePaginationParams extracts the 'offset' and 'limit' parameters from the request's query parameters. @@ -58,7 +60,7 @@ func SendPaginatedResponse(ctx *gin.Context, records interface{}, offset, limit, // Check if v is not a slice. if v.Kind() != reflect.Slice { - WriteAndLogError(ctx, schemas.BadRequest, http.StatusBadRequest, errors.New("records not a valid list")) + WriteAndLogError(ctx, goerrors.BadRequest, http.StatusBadRequest, errors.New("records not a valid list")) return } diff --git a/internal/utils/request.go b/internal/utils/request.go index 3a89c34..bb64f5e 100644 --- a/internal/utils/request.go +++ b/internal/utils/request.go @@ -2,6 +2,7 @@ package utils import ( "github.com/gin-gonic/gin" + "github.com/wwi21seb-projekt/errors-go/goerrors" "github.com/wwi21seb-projekt/server-alpha/internal/schemas" ) @@ -14,7 +15,7 @@ func WriteAndLogResponse(ctx *gin.Context, response interface{}, statusCode int) // WriteAndLogError logs the provided error and sends an error response with the specified status code and error details. // If encoding the error response fails, it logs and sends an InternalServerError response. -func WriteAndLogError(c *gin.Context, customErr *schemas.CustomError, statusCode int, err error) { +func WriteAndLogError(c *gin.Context, customErr *goerrors.CustomError, statusCode int, err error) { LogMessageWithFields(c, "error", "Error occurred: "+err.Error()) LogMessageWithFields(c, "error", "Returning "+customErr.Code+" / "+customErr.Message) errorDto := &schemas.ErrorDTO{ diff --git a/internal/utils/transaction.go b/internal/utils/transaction.go index 1f0b691..2db13cd 100644 --- a/internal/utils/transaction.go +++ b/internal/utils/transaction.go @@ -2,11 +2,12 @@ package utils import ( "errors" + "net/http" + "github.com/gin-gonic/gin" "github.com/jackc/pgx/v5" + "github.com/wwi21seb-projekt/errors-go/goerrors" "github.com/wwi21seb-projekt/server-alpha/internal/interfaces" - "github.com/wwi21seb-projekt/server-alpha/internal/schemas" - "net/http" ) // BeginTransaction begins a new database transaction with a context deadline. @@ -18,7 +19,7 @@ func BeginTransaction(ctx *gin.Context, pool interfaces.PgxPoolIface) pgx.Tx { tx, err := pool.Begin(ctx) if err != nil { LogMessageWithFieldsAndError(ctx, "error", "Error beginning transaction", err) - WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return nil } @@ -40,7 +41,7 @@ func RollbackTransaction(ctx *gin.Context, tx pgx.Tx, err error) { } LogMessageWithFields(ctx, "debug", "Context canceled") - WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) } LogMessageWithFields(ctx, "debug", "Transaction rolled back") } @@ -60,7 +61,7 @@ func CommitTransaction(ctx *gin.Context, tx pgx.Tx) error { if err != nil { LogMessageWithFieldsAndError(ctx, "error", "Error committing transaction", err) - WriteAndLogError(ctx, schemas.DatabaseError, http.StatusInternalServerError, err) + WriteAndLogError(ctx, goerrors.DatabaseError, http.StatusInternalServerError, err) return err }