to much to describe, everything in PR
This commit is contained in:
@@ -1,13 +1,195 @@
|
||||
package handler
|
||||
|
||||
import "net/http"
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
func (s *Server) ListDrivers(w http.ResponseWriter, r *http.Request) {}
|
||||
"github.com/anxi0uz/logiflow/internal/api"
|
||||
"github.com/anxi0uz/logiflow/internal/models"
|
||||
storage "github.com/anxi0uz/logiflow/pkg"
|
||||
"github.com/google/uuid"
|
||||
"github.com/gosimple/slug"
|
||||
"github.com/huandu/go-sqlbuilder"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func (s *Server) CreateDriver(w http.ResponseWriter, r *http.Request) {}
|
||||
func (s *Server) ListDrivers(w http.ResponseWriter, r *http.Request, params api.ListDriversParams) {}
|
||||
|
||||
func (s *Server) GetDriver(w http.ResponseWriter, r *http.Request, slug string) {}
|
||||
func (s *Server) CreateDriver(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
claims := ctx.Value("user").(*Claims)
|
||||
if claims.Role != "admin" {
|
||||
slog.WarnContext(ctx, "unusual try from not allowed role", slog.String("Role", claims.Role), slog.String("id", claims.ID.String()))
|
||||
s.JSON(w, r, http.StatusForbidden, MsgForbidden, RespError)
|
||||
return
|
||||
}
|
||||
var req api.DriverCreate
|
||||
|
||||
func (s *Server) UpdateDriver(w http.ResponseWriter, r *http.Request, slug string) {}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
slog.ErrorContext(ctx, "Invalid request body", slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusBadRequest, MsgInvalidBody, RespError)
|
||||
return
|
||||
}
|
||||
passwordHash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
slog.ErrorContext(ctx, "error while generating passwordhash", slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
now := time.Now()
|
||||
userid := uuid.New()
|
||||
user := models.User{
|
||||
ID: userid,
|
||||
Slug: s.GenerateUserSlug(req.FullName, userid),
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
Role: "driver",
|
||||
Email: string(req.Email),
|
||||
PasswordHash: string(passwordHash),
|
||||
FullName: req.FullName,
|
||||
}
|
||||
|
||||
func (s *Server) DeleteDriver(w http.ResponseWriter, r *http.Request, slug string) {}
|
||||
tx, err := s.DB.Begin(ctx)
|
||||
if err != nil {
|
||||
slog.ErrorContext(ctx, "Unable to open transaction", slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
defer tx.Rollback(ctx)
|
||||
|
||||
if err := storage.Create(ctx, "users", user, tx); err != nil {
|
||||
slog.ErrorContext(ctx, "Unable to create user", slog.String("error", err.Error()), slog.Any("user", user))
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
id := uuid.New()
|
||||
driver := models.Driver{
|
||||
ID: id,
|
||||
UserID: userid,
|
||||
VehicleID: req.VehicleId,
|
||||
LicenseNumber: req.LicenseNumber,
|
||||
LicenseExpiry: req.LicenseExpiry.Time,
|
||||
Rating: 0,
|
||||
Slug: slug.Make(req.FullName + " " + req.LicenseNumber),
|
||||
}
|
||||
|
||||
if err := storage.Create(ctx, "drivers", driver, tx); err != nil {
|
||||
slog.ErrorContext(ctx, "Unable to create driver", slog.String("error", err.Error()), slog.Any("driver", driver))
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
slog.ErrorContext(ctx, "Error while commiting transaction", slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
s.JSON(w, r, http.StatusCreated, driver, "driver")
|
||||
}
|
||||
|
||||
func (s *Server) UpdateMyDriverStatus(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
claims, ok := ctx.Value("user").(*Claims)
|
||||
if !ok {
|
||||
slog.ErrorContext(ctx, "Unable to convert claims", slog.Any("claims", ctx.Value("user")))
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
var req api.DriverStatusUpdate
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
s.JSON(w, r, http.StatusBadRequest, MsgInvalidBody, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
if err := storage.Update(ctx, "drivers", models.Driver{Status: string(req.Status)}, s.DB, func(ub *sqlbuilder.UpdateBuilder) {
|
||||
ub.Where(ub.Equal("user_id", claims.ID))
|
||||
}); err != nil {
|
||||
if errors.Is(err, storage.ErrNotFound) {
|
||||
slog.ErrorContext(ctx, "No driver with that user id not found", slog.String("user id", claims.ID.String()))
|
||||
s.JSON(w, r, http.StatusNotFound, "driver not found", RespNotFound)
|
||||
return
|
||||
}
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
s.JSON(w, r, http.StatusOK, "status updated", RespSuccess)
|
||||
}
|
||||
|
||||
func (s *Server) GetDriver(w http.ResponseWriter, r *http.Request, slug string) {
|
||||
ctx := r.Context()
|
||||
|
||||
driver, err := storage.GetOne[models.Driver](ctx, s.DB, "drivers", func(sb *sqlbuilder.SelectBuilder) {
|
||||
sb.Where(sb.Equal("slug", slug))
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, storage.ErrNotFound) {
|
||||
slog.ErrorContext(ctx, "No driver found with that slug", slog.String("slug", slug))
|
||||
s.JSON(w, r, http.StatusNotFound, MsgNotFound, RespNotFound)
|
||||
return
|
||||
}
|
||||
slog.ErrorContext(ctx, "Error while finding driver with that slug", slog.String("slug", slug), slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
s.JSON(w, r, http.StatusOK, driver, RespSuccess)
|
||||
}
|
||||
|
||||
func (s *Server) UpdateDriver(w http.ResponseWriter, r *http.Request, slug string) {
|
||||
ctx := r.Context()
|
||||
|
||||
var req api.DriverUpdate
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
slog.ErrorContext(ctx, "Invalid request body", slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusBadRequest, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
driver := models.Driver{
|
||||
LicenseNumber: *req.LicenseNumber,
|
||||
LicenseExpiry: req.LicenseExpiry.Time,
|
||||
Status: string(*req.Status),
|
||||
VehicleID: req.VehicleId,
|
||||
}
|
||||
|
||||
if err := storage.Update(ctx, "drivers", driver, s.DB, func(sb *sqlbuilder.UpdateBuilder) {
|
||||
sb.Where(sb.Equal("slug", slug))
|
||||
}); err != nil {
|
||||
if errors.Is(err, storage.ErrNotFound) {
|
||||
slog.ErrorContext(ctx, "no drivers found with that slug", slog.String("slug", slug), slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusNotFound, MsgNotFound, RespNotFound)
|
||||
return
|
||||
}
|
||||
slog.ErrorContext(ctx, "Error while updating driver with that slug", slog.String("slug", slug), slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
s.JSON(w, r, http.StatusOK, slug, RespSuccess)
|
||||
}
|
||||
|
||||
func (s *Server) DeleteDriver(w http.ResponseWriter, r *http.Request, slug string) {
|
||||
ctx := r.Context()
|
||||
|
||||
err := storage.Delete[models.Driver](ctx, "drivers", s.DB, func(sb *sqlbuilder.DeleteBuilder) {
|
||||
sb.Where(sb.Equal("slug", slug))
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, storage.ErrNotFound) {
|
||||
s.JSON(w, r, http.StatusNotFound, "No driver with that slug found", RespNotFound)
|
||||
return
|
||||
}
|
||||
slog.ErrorContext(ctx, "unable to delete vehicle with that slug", slog.String("slug", slug), slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
s.JSON(w, r, http.StatusOK, slug, "deleted")
|
||||
|
||||
}
|
||||
|
||||
14
internal/handler/notification.go
Normal file
14
internal/handler/notification.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/anxi0uz/logiflow/internal/api"
|
||||
openapi_types "github.com/oapi-codegen/runtime/types"
|
||||
)
|
||||
|
||||
func (s *Server) ListNotifications(w http.ResponseWriter, r *http.Request, params api.ListNotificationsParams) {
|
||||
}
|
||||
|
||||
func (s *Server) MarkNotificationRead(w http.ResponseWriter, r *http.Request, id openapi_types.UUID) {
|
||||
}
|
||||
@@ -3,10 +3,11 @@ package handler
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/anxi0uz/logiflow/internal/api"
|
||||
openapi_types "github.com/oapi-codegen/runtime/types"
|
||||
)
|
||||
|
||||
func (s *Server) ListOrders(w http.ResponseWriter, r *http.Request) {}
|
||||
func (s *Server) ListOrders(w http.ResponseWriter, r *http.Request, params api.ListOrdersParams) {}
|
||||
|
||||
func (s *Server) CreateOrder(w http.ResponseWriter, r *http.Request) {}
|
||||
|
||||
@@ -15,3 +16,8 @@ func (s *Server) GetOrder(w http.ResponseWriter, r *http.Request, id openapi_typ
|
||||
func (s *Server) CancelOrder(w http.ResponseWriter, r *http.Request, id openapi_types.UUID) {}
|
||||
|
||||
func (s *Server) UpdateOrderStatus(w http.ResponseWriter, r *http.Request, id openapi_types.UUID) {}
|
||||
|
||||
func (s *Server) GetOrdersReport(w http.ResponseWriter, r *http.Request, params api.GetOrdersReportParams) {
|
||||
}
|
||||
|
||||
func (s *Server) GetDashboard(w http.ResponseWriter, r *http.Request) {}
|
||||
|
||||
@@ -26,6 +26,19 @@ type ctxKey string
|
||||
const (
|
||||
requestIDKey ctxKey = "X-Request-ID"
|
||||
tokenKey ctxKey = "Authorization"
|
||||
|
||||
// response messages
|
||||
MsgInternalError = "Internal server error"
|
||||
MsgInvalidBody = "Invalid request body"
|
||||
MsgNotFound = "Not found"
|
||||
MsgUnauthorized = "Unauthorized"
|
||||
MsgMissingToken = "Missing token"
|
||||
MsgForbidden = "Forbidden"
|
||||
|
||||
// response types
|
||||
RespError = "error"
|
||||
RespSuccess = "success"
|
||||
RespNotFound = "not found"
|
||||
)
|
||||
|
||||
type responseOptions struct {
|
||||
@@ -112,7 +125,7 @@ func (s *Server) AuthMiddleware(next http.Handler) http.Handler {
|
||||
|
||||
tokenStr := r.Header.Get("Authorization")
|
||||
if tokenStr == "" {
|
||||
s.JSON(w, r, http.StatusUnauthorized, "missing token", "error")
|
||||
s.JSON(w, r, http.StatusUnauthorized, MsgMissingToken, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -121,7 +134,7 @@ func (s *Server) AuthMiddleware(next http.Handler) http.Handler {
|
||||
claims, err := s.validateAccessToken(r.Context(), tokenStr)
|
||||
if err != nil {
|
||||
slog.WarnContext(r.Context(), "Токен не прошел валидацию", slog.String("Token", tokenStr), slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusUnauthorized, "токен не прошёл валидацию", "error")
|
||||
s.JSON(w, r, http.StatusUnauthorized, MsgUnauthorized, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ func (s *Server) AuthLogin(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req api.LoginRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
s.JSON(w, r, http.StatusBadRequest, "Ошибка при получении данных", "error")
|
||||
s.JSON(w, r, http.StatusBadRequest, MsgInvalidBody, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -65,32 +65,32 @@ func (s *Server) AuthLogout(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
cookie, err := r.Cookie("refresh_token")
|
||||
if err != nil {
|
||||
s.JSON(w, r, http.StatusUnauthorized, "Missing refresh token", "error")
|
||||
s.JSON(w, r, http.StatusUnauthorized, MsgMissingToken, RespError)
|
||||
return
|
||||
}
|
||||
refreshStr := cookie.Value
|
||||
if refreshStr == "" {
|
||||
s.JSON(w, r, http.StatusUnauthorized, "Empty refresh token", "error")
|
||||
s.JSON(w, r, http.StatusUnauthorized, MsgUnauthorized, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
refreshKey := "refresh_token:" + refreshStr
|
||||
if err := s.Redis.Del(ctx, refreshKey).Err(); err != nil {
|
||||
slog.ErrorContext(ctx, "Error while removing refresh token from redis", slog.String("token", refreshStr), slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusUnauthorized, "Internal server error", "error")
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
tokenStr := r.Header.Get("Authorization")
|
||||
if tokenStr == "" {
|
||||
s.JSON(w, r, http.StatusUnauthorized, "missing token", "error")
|
||||
s.JSON(w, r, http.StatusUnauthorized, MsgMissingToken, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
tokenKey := "access_token:" + tokenStr
|
||||
if err := s.Redis.Del(ctx, tokenKey).Err(); err != nil {
|
||||
slog.ErrorContext(ctx, "Error while removing access token from redis", slog.String("token", tokenStr), slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusUnauthorized, "Internal server error", "error")
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -99,17 +99,17 @@ func (s *Server) AuthRefresh(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
cookie, err := r.Cookie("refresh_token")
|
||||
if err != nil {
|
||||
s.JSON(w, r, http.StatusUnauthorized, "Missing refresh token", "error")
|
||||
s.JSON(w, r, http.StatusUnauthorized, MsgMissingToken, RespError)
|
||||
return
|
||||
}
|
||||
refreshStr := cookie.Value
|
||||
if refreshStr == "" {
|
||||
s.JSON(w, r, http.StatusUnauthorized, "Empty refresh token", "error")
|
||||
s.JSON(w, r, http.StatusUnauthorized, MsgUnauthorized, RespError)
|
||||
return
|
||||
}
|
||||
key := "refresh_token:" + refreshStr
|
||||
if _, err := s.Redis.Get(ctx, key).Result(); err == redis.Nil {
|
||||
s.JSON(w, r, http.StatusUnauthorized, "No active refresh token", "error")
|
||||
s.JSON(w, r, http.StatusUnauthorized, MsgUnauthorized, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -119,13 +119,13 @@ func (s *Server) AuthRefresh(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if !ok {
|
||||
slog.ErrorContext(ctx, "Error parsing claims", slog.Any("claims", claims))
|
||||
s.JSON(w, r, http.StatusInternalServerError, nil, "internal server error")
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
userID := claims.ID
|
||||
if userID == uuid.Nil {
|
||||
s.JSON(w, r, http.StatusUnauthorized, "Missing user id in token", "error")
|
||||
s.JSON(w, r, http.StatusUnauthorized, MsgUnauthorized, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ func (s *Server) AuthRefresh(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
if err != nil {
|
||||
slog.ErrorContext(ctx, "user with that id not found", slog.Any("id", userID.String()), "error", err.Error())
|
||||
s.JSON(w, r, http.StatusUnauthorized, "Invalid user id in token", "error")
|
||||
s.JSON(w, r, http.StatusUnauthorized, MsgUnauthorized, RespError)
|
||||
return
|
||||
}
|
||||
s.issueTokens(w, r, user)
|
||||
@@ -146,13 +146,13 @@ func (s *Server) AuthRegister(w http.ResponseWriter, r *http.Request) {
|
||||
var req api.RegisterRequest
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
s.JSON(w, r, http.StatusBadRequest, "invalid request body", "error")
|
||||
s.JSON(w, r, http.StatusBadRequest, MsgInvalidBody, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
passwordHash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
s.JSON(w, r, http.StatusInternalServerError, "error while hashing password", "error")
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ func (s *Server) AuthRegister(w http.ResponseWriter, r *http.Request) {
|
||||
Slug: s.GenerateUserSlug(req.FullName, uuid),
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
Role: string(req.Role),
|
||||
Role: "client",
|
||||
Email: string(req.Email),
|
||||
PasswordHash: string(passwordHash),
|
||||
FullName: req.FullName,
|
||||
@@ -173,7 +173,7 @@ func (s *Server) AuthRegister(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if err := storage.Create(ctx, "users", user, s.DB); err != nil {
|
||||
slog.ErrorContext(ctx, "Error while creating user", slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, "Server error", "error")
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
s.issueTokens(w, r, &user)
|
||||
@@ -185,14 +185,14 @@ func (s *Server) DeleteMe(w http.ResponseWriter, r *http.Request) {
|
||||
claims, ok := claimsValue.(*Claims)
|
||||
if !ok {
|
||||
slog.ErrorContext(ctx, "Error while converting claims", slog.Any("claims", claimsValue))
|
||||
s.JSON(w, r, http.StatusInternalServerError, "Internal server error", "error")
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
userID := claims.ID
|
||||
tx, err := s.DB.Begin(ctx)
|
||||
if err != nil {
|
||||
slog.ErrorContext(ctx, "Error while begining transaction", slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, "Internal server error", "error")
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
defer tx.Rollback(ctx)
|
||||
@@ -202,7 +202,7 @@ func (s *Server) DeleteMe(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
if err != nil {
|
||||
slog.ErrorContext(ctx, "Error while deleting user", slog.String("error", err.Error()), slog.String("id", userID.String()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, "Internal server error", "error")
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -210,29 +210,29 @@ func (s *Server) DeleteMe(w http.ResponseWriter, r *http.Request) {
|
||||
tokenKey := "access_token:" + jwt
|
||||
if err := s.Redis.Del(ctx, tokenKey).Err(); err != nil {
|
||||
slog.ErrorContext(ctx, "Error while deleting access token from redis", slog.String("token", jwt))
|
||||
s.JSON(w, r, http.StatusInternalServerError, "Internal server error", "error")
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
cookie, err := r.Cookie("refresh_token")
|
||||
if err != nil {
|
||||
s.JSON(w, r, http.StatusUnauthorized, "Missing refresh token", "error")
|
||||
s.JSON(w, r, http.StatusUnauthorized, MsgMissingToken, RespError)
|
||||
return
|
||||
}
|
||||
refreshStr := cookie.Value
|
||||
if refreshStr == "" {
|
||||
s.JSON(w, r, http.StatusUnauthorized, "Empty refresh token", "error")
|
||||
s.JSON(w, r, http.StatusUnauthorized, MsgUnauthorized, RespError)
|
||||
return
|
||||
}
|
||||
key := "refresh_token:" + refreshStr
|
||||
if err := s.Redis.Del(ctx, key).Err(); err != nil {
|
||||
slog.ErrorContext(ctx, "Error while deleting refresh token from redis", slog.String("token", refreshStr))
|
||||
s.JSON(w, r, http.StatusInternalServerError, "Internal server error", "error")
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
slog.ErrorContext(ctx, "Error while committing transaction", slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, "Internal server error", "error")
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ func (s *Server) GetMe(w http.ResponseWriter, r *http.Request) {
|
||||
claims, ok := claimsValue.(*Claims)
|
||||
if !ok {
|
||||
slog.ErrorContext(ctx, "Error while converting claims", slog.Any("claims", claimsValue))
|
||||
s.JSON(w, r, http.StatusInternalServerError, "Internal server error", "error")
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -258,13 +258,15 @@ func (s *Server) GetMe(w http.ResponseWriter, r *http.Request) {
|
||||
slog.ErrorContext(ctx, "No user was found with that id",
|
||||
slog.String("id", userID.String()),
|
||||
slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, "invalid user id", "error")
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
s.JSON(w, r, http.StatusOK, user, "ok")
|
||||
}
|
||||
func (s *Server) UpdateMe(w http.ResponseWriter, r *http.Request) {}
|
||||
|
||||
func (s *Server) GetMyTrips(w http.ResponseWriter, r *http.Request) {}
|
||||
|
||||
func (s *Server) issueTokens(w http.ResponseWriter, r *http.Request, user *models.User) {
|
||||
access, err := s.generateAccessToken(user, s.Config.RedisAccessTokenDur())
|
||||
if err != nil {
|
||||
@@ -274,7 +276,7 @@ func (s *Server) issueTokens(w http.ResponseWriter, r *http.Request, user *model
|
||||
refresh, err := s.generateRefreshToken()
|
||||
if err != nil {
|
||||
slog.ErrorContext(r.Context(), "generate refresh token failed", slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, "Failure during generating tokens", "error")
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -283,14 +285,14 @@ func (s *Server) issueTokens(w http.ResponseWriter, r *http.Request, user *model
|
||||
err = s.Redis.Set(r.Context(), key, "valid", s.Config.RedisAccessTokenDur()).Err()
|
||||
if err != nil {
|
||||
slog.ErrorContext(r.Context(), "Failed to set access token in redis", slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, "Server error", "error")
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
err = s.Redis.Set(r.Context(), refreshkey, "valid", s.Config.RedisRefreshTokenDur()).Err()
|
||||
if err != nil {
|
||||
slog.ErrorContext(r.Context(), "Failed to set refresh token in redis", slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, "Server error", "error")
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,155 @@
|
||||
package handler
|
||||
|
||||
import "net/http"
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
func (s *Server) ListVehicles(w http.ResponseWriter, r *http.Request) {}
|
||||
"github.com/anxi0uz/logiflow/internal/api"
|
||||
"github.com/anxi0uz/logiflow/internal/models"
|
||||
storage "github.com/anxi0uz/logiflow/pkg"
|
||||
"github.com/google/uuid"
|
||||
"github.com/gosimple/slug"
|
||||
"github.com/huandu/go-sqlbuilder"
|
||||
)
|
||||
|
||||
func (s *Server) CreateVehicle(w http.ResponseWriter, r *http.Request) {}
|
||||
func (s *Server) ListVehicles(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
func (s *Server) GetVehicle(w http.ResponseWriter, r *http.Request, slug string) {}
|
||||
vehicles, err := storage.GetAll[models.Vehicle](ctx, "vehicles", s.DB)
|
||||
if err != nil {
|
||||
slog.ErrorContext(ctx, "Unable to get all vehicles", slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
s.JSON(w, r, http.StatusOK, vehicles, RespSuccess)
|
||||
}
|
||||
|
||||
func (s *Server) UpdateVehicle(w http.ResponseWriter, r *http.Request, slug string) {}
|
||||
func (s *Server) CreateVehicle(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
func (s *Server) DeleteVehicle(w http.ResponseWriter, r *http.Request, slug string) {}
|
||||
var req api.VehicleCreate
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
slog.ErrorContext(ctx, "Invalid request body", slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusBadRequest, MsgInvalidBody, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
id := uuid.New()
|
||||
vehicle := models.Vehicle{
|
||||
ID: id,
|
||||
PlateNumber: req.PlateNumber,
|
||||
Slug: slug.Make(req.PlateNumber),
|
||||
}
|
||||
|
||||
if req.Brand != nil {
|
||||
vehicle.Brand = *req.Brand
|
||||
}
|
||||
if req.Model != nil {
|
||||
vehicle.Model = *req.Model
|
||||
}
|
||||
if req.Year != nil {
|
||||
vehicle.Year = *req.Year
|
||||
}
|
||||
if req.CapacityKg != nil {
|
||||
vehicle.CapacityKg = float64(*req.CapacityKg)
|
||||
}
|
||||
if req.CapacityM3 != nil {
|
||||
vehicle.CapacityM3 = float64(*req.CapacityM3)
|
||||
}
|
||||
|
||||
if err := storage.Create(ctx, "vehicles", vehicle, s.DB); err != nil {
|
||||
slog.ErrorContext(ctx, "Unable to create vehicle", slog.Any("vehicle", vehicle))
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
s.JSON(w, r, http.StatusCreated, vehicle, "vehicle")
|
||||
}
|
||||
|
||||
func (s *Server) GetVehicle(w http.ResponseWriter, r *http.Request, slug string) {
|
||||
ctx := r.Context()
|
||||
|
||||
vehicle, err := storage.GetOne[models.Vehicle](ctx, s.DB, "vehicles", func(sb *sqlbuilder.SelectBuilder) {
|
||||
sb.Where(sb.Equal("slug", slug))
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, storage.ErrNotFound) {
|
||||
s.JSON(w, r, http.StatusNotFound, "vehicle not found with that slug", RespNotFound)
|
||||
return
|
||||
}
|
||||
slog.ErrorContext(ctx, "no vehicle found in db with that slug", slog.String("slug", slug), slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
s.JSON(w, r, http.StatusOK, vehicle, "vehicle")
|
||||
}
|
||||
|
||||
func (s *Server) UpdateVehicle(w http.ResponseWriter, r *http.Request, slug string) {
|
||||
ctx := r.Context()
|
||||
|
||||
var req api.VehicleUpdate
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
slog.ErrorContext(ctx, "Invalid request body", slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusBadRequest, MsgInvalidBody, RespError)
|
||||
return
|
||||
}
|
||||
|
||||
vehicle, err := storage.GetOne[models.Vehicle](ctx, s.DB, "vehicles", func(sb *sqlbuilder.SelectBuilder) {
|
||||
sb.Where(sb.Equal("slug", slug))
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, storage.ErrNotFound) {
|
||||
s.JSON(w, r, http.StatusNotFound, "vehicle not found with that slug", RespNotFound)
|
||||
return
|
||||
}
|
||||
slog.ErrorContext(ctx, "no vehicle found in db with that slug", slog.String("slug", slug), slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
if req.Status != nil {
|
||||
vehicle.Status = string(*req.Status)
|
||||
}
|
||||
if req.Brand != nil {
|
||||
vehicle.Brand = *req.Brand
|
||||
}
|
||||
if req.Model != nil {
|
||||
vehicle.Model = *req.Model
|
||||
}
|
||||
if req.Year != nil {
|
||||
vehicle.Year = *req.Year
|
||||
}
|
||||
if req.CapacityKg != nil {
|
||||
vehicle.CapacityKg = float64(*req.CapacityKg)
|
||||
}
|
||||
if req.CapacityM3 != nil {
|
||||
vehicle.CapacityM3 = float64(*req.CapacityM3)
|
||||
}
|
||||
if err := storage.Update(ctx, "vehicles", *vehicle, s.DB, func(ub *sqlbuilder.UpdateBuilder) {
|
||||
ub.Where(ub.Equal("slug", slug))
|
||||
}); err != nil {
|
||||
slog.ErrorContext(ctx, "failed to update vehicle", slog.String("slug", slug), slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
s.JSON(w, r, http.StatusOK, vehicle, "vehicle")
|
||||
}
|
||||
|
||||
func (s *Server) DeleteVehicle(w http.ResponseWriter, r *http.Request, slug string) {
|
||||
ctx := r.Context()
|
||||
|
||||
err := storage.Delete[models.Vehicle](ctx, "vehicles", s.DB, func(sb *sqlbuilder.DeleteBuilder) {
|
||||
sb.Where(sb.Equal("slug", slug))
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, storage.ErrNotFound) {
|
||||
s.JSON(w, r, http.StatusNotFound, "no vehicle with that slug found", RespNotFound)
|
||||
return
|
||||
}
|
||||
slog.ErrorContext(ctx, "unable to delete vehicle with that slug", slog.String("slug", slug), slog.String("error", err.Error()))
|
||||
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||
return
|
||||
}
|
||||
s.JSON(w, r, http.StatusOK, slug, "deleted")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user