196 lines
6.6 KiB
Go
196 lines
6.6 KiB
Go
package handler
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"log/slog"
|
|
"net/http"
|
|
"time"
|
|
|
|
"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) ListDrivers(w http.ResponseWriter, r *http.Request, params api.ListDriversParams) {}
|
|
|
|
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
|
|
|
|
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,
|
|
}
|
|
|
|
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")
|
|
|
|
}
|