package handlers import ( "fmt" "net/http" "otaupdate/controllers" "otaupdate/services" "github.com/fiskerinc/cloud-services/pkg/httphandlers" "github.com/fiskerinc/cloud-services/pkg/logger" "github.com/fiskerinc/cloud-services/pkg/mongo" "github.com/fiskerinc/cloud-services/pkg/utils" "github.com/fiskerinc/cloud-services/pkg/validator" "github.com/fiskerinc/cloud-services/pkg/common" "github.com/fiskerinc/cloud-services/pkg/utils/elptr" "github.com/julienschmidt/httprouter" ) // HandleFleetVehicleAdd godoc // @Summary Add vehicle to fleet // @Description Add vehicle to fleet // @Accept json // @Produce json // @Param Authorization header string false "Bearer " // @Param Api-Key header string false "" // @Param name path string true "Name" // @Param config body FleetVehicleParams true "Vehicle data" // @Success 200 {object} common.SubscriptionConfiguration // @Failure 400 {object} common.JSONError "Bad request" // @Failure 401 {object} common.JSONError "Unauthorized" // @Failure 503 {object} common.JSONError "Service unavailable" // @Router /fleet/{name}/vehicles/add [post] func HandleFleetVehicleAdd(w http.ResponseWriter, r *http.Request) { fleetVehicleAdd.Handle(w, r) } var fleetVehicleAdd = controllers.NewMongoUpdate(&fleetVehicleAddHelper{}) type fleetVehicleAddHelper struct{} func (h *fleetVehicleAddHelper) ParseUpdateURLParams(r *http.Request) interface{} { req := &mongo.Fleet{} params := httprouter.ParamsFromContext(r.Context()) req.Name = params.ByName("name") return req } func (h *fleetVehicleAddHelper) ValidateFields(model interface{}) error { result, ok := model.(*mongo.Fleet) if !ok { return nil } err := validator.ValidateField(result.Name, "required,fleet") if err != nil { return controllers.ErrorPKRequired } return nil } func (h *fleetVehicleAddHelper) NewModel() interface{} { return &FleetVehicleParams{} } func (h *fleetVehicleAddHelper) ParseRequestBody(r *http.Request, model interface{}) error { return httphandlers.ParseRequest(r, model) } func (h *fleetVehicleAddHelper) QueryUpdate(filter interface{}, model interface{}) error { client, err := services.GetMongoClient() if err != nil { return err } fvp := model.(*FleetVehicleParams) if fvp.CANBus == nil { fvp.CANBus = &common.CANBus{Enabled: true} } if fvp.CANBus.DTCEnabled == nil { fvp.CANBus.DTCEnabled = elptr.ElPtr(true) } if len(fvp.VIN) > 0 { fvp.VINs = append(fvp.VINs, fvp.VIN) } // clear out the VIN (single) if it was merged into the new property // otherwise persist existing behavior if len(fvp.VIN) > 0 && len(fvp.VINs) > 1 { fvp.VIN = "" } cars, err := utils.ParseVINs(fvp.VINs) if err != nil { return err } for _, car := range cars { hasVehicle := doesVehicleExist(car.VIN) if !hasVehicle { logger.Warn().Msgf("tried to add a non-existent car %s to fleet %s", car.VIN, filter.(*mongo.Fleet).Name) err = fmt.Errorf("vin %s was not found in database", car.VIN) return err } } err = client.GetFleets().AddVehiclesToFleet(filter.(*mongo.Fleet).Name, fvp.VINs) if err != nil { return err } err = ResetVehiclesConfigCache(fvp.VINs) if err != nil { return err } return nil } func doesVehicleExist(vin string) bool { count, err := services.GetDB().GetCars().Count(&common.Car{VIN: vin}) if err != nil { return false } return count == 1 } type FleetVehicleParams struct { VIN string `json:"vin" validate:"required_without=VINs,omitempty,vin"` VINs []string `json:"vins,omitempty" validate:"required_without=VIN,max=1000,dive,vin"` LogLevel common.LogLevel `json:"log_level,omitempty" swaggertype:"string"` CANBus *common.CANBus `json:"canbus,omitempty"` IDPSEnabled bool `json:"idps_enabled,omitempty"` }