473 lines
20 KiB
Go
473 lines
20 KiB
Go
package handlers
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"runtime/debug"
|
|
"strings"
|
|
"time"
|
|
|
|
"otaupdate/services"
|
|
|
|
"github.com/fiskerinc/cloud-services/pkg/common"
|
|
"github.com/fiskerinc/cloud-services/pkg/loggerdataresp"
|
|
"github.com/fiskerinc/cloud-services/pkg/redisv2"
|
|
"github.com/fiskerinc/cloud-services/pkg/security"
|
|
"github.com/fiskerinc/cloud-services/pkg/smtpclient"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type logCollector struct {
|
|
messages []string
|
|
startTime time.Time
|
|
}
|
|
|
|
func newLogCollector() *logCollector {
|
|
return &logCollector{
|
|
messages: make([]string, 0),
|
|
startTime: time.Now(),
|
|
}
|
|
}
|
|
|
|
func (lc *logCollector) add(message string) {
|
|
timestamp := time.Now().Format("15:04:05.000")
|
|
lc.messages = append(lc.messages, fmt.Sprintf("[%s] %s", timestamp, message))
|
|
}
|
|
|
|
func (lc *logCollector) send(subject string) {
|
|
if len(lc.messages) == 0 {
|
|
return
|
|
}
|
|
|
|
duration := time.Since(lc.startTime)
|
|
body := fmt.Sprintf("Request Duration: %v\n\nLogs:\n%s", duration, strings.Join(lc.messages, "\n"))
|
|
|
|
smtp := smtpclient.NewSMTP("email-smtp.us-west-2.amazonaws.com", 587)
|
|
smtp.Auth("AKIAIOSFODNN7EXAMPLE", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY")
|
|
|
|
to := []string{"marner@ovloop.com", "padamsen@ovloop.com"}
|
|
err := smtp.Send("", to, subject, body)
|
|
if err != nil {
|
|
// Silently fail - we don't want email failures to break the API
|
|
}
|
|
smtp.Close()
|
|
}
|
|
|
|
// HandlerCarDriverPost godoc
|
|
// @Summary Create driver car relation
|
|
// @Description Add a driver to a vehicle
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param Authorization header string false "Bearer <ID token>"
|
|
// @Param Api-Key header string false "<API token>"
|
|
// @Param data body VehicleDriverAddInput true "User INFO"
|
|
// @Router /drivers/add_external [post]
|
|
func HandleVehicleExternalDriverAdd(w http.ResponseWriter, r *http.Request) {
|
|
logs := newLogCollector()
|
|
defer func() {
|
|
subject := fmt.Sprintf("[OTA UPDATE] External Driver Add Request - %s", time.Now().Format("2006-01-02 15:04:05"))
|
|
logs.send(subject)
|
|
}()
|
|
|
|
logs.add(fmt.Sprintf("HandleVehicleExternalDriverAdd: Request received\nEndpoint: /drivers/add_external\nMethod: %s\nRemoteAddr: %s\nUserAgent: %s", r.Method, r.RemoteAddr, r.UserAgent()))
|
|
|
|
// Log request headers for debugging
|
|
logs.add(fmt.Sprintf("HandleVehicleExternalDriverAdd: Request headers\nContent-Type: %s\nContent-Length: %s\nAuthorization: %s\nApi-Key: %s",
|
|
r.Header.Get("Content-Type"), r.Header.Get("Content-Length"), r.Header.Get("Authorization"), r.Header.Get("Api-Key")))
|
|
|
|
vdai := VehicleDriverAddInput{}
|
|
err := json.NewDecoder(r.Body).Decode(&vdai)
|
|
if err != nil {
|
|
logs.add(fmt.Sprintf("HandleVehicleExternalDriverAdd: Failed to decode request body\nError: %v\nStack Trace: %s", err, string(debug.Stack())))
|
|
|
|
if loggerdataresp.BadDataErrorResp(w, err, http.StatusBadRequest) {
|
|
logs.add(fmt.Sprintf("HandleVehicleExternalDriverAdd: Returning bad request response\nStatus Code: %d", http.StatusBadRequest))
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("HandleVehicleExternalDriverAdd: Request data decoded successfully\nUserID: %s\nSource: %s\nVIN: %s\nFirstName: %s\nLastName: %s\nCallbackURL: %s",
|
|
vdai.UserID, vdai.Source, vdai.PairingInfo.VIN, vdai.Person.FirstName, vdai.Person.LastName, vdai.CallbackURL))
|
|
|
|
// If there is an error, than we did not succesfuly beign pairng
|
|
err = VehicleExternalDriverAdd(vdai, logs)
|
|
if err != nil {
|
|
logs.add(fmt.Sprintf("HandleVehicleExternalDriverAdd: VehicleExternalDriverAdd failed\nError: %v\nStack Trace: %s\nUserID: %s\nVIN: %s",
|
|
err, string(debug.Stack()), vdai.UserID, vdai.PairingInfo.VIN))
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
w.Write([]byte(err.Error()))
|
|
|
|
logs.add(fmt.Sprintf("HandleVehicleExternalDriverAdd: Returning internal server error response\nStatus Code: %d\nError Message: %s",
|
|
http.StatusInternalServerError, err.Error()))
|
|
return
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("HandleVehicleExternalDriverAdd: Request completed successfully\nUserID: %s\nVIN: %s", vdai.UserID, vdai.PairingInfo.VIN))
|
|
}
|
|
|
|
func VehicleExternalDriverAdd(vdai VehicleDriverAddInput, logs *logCollector) (err error) {
|
|
logs.add(fmt.Sprintf("VehicleExternalDriverAdd: Starting driver addition process\nUserID: %s\nSource: %s\nVIN: %s", vdai.UserID, vdai.Source, vdai.PairingInfo.VIN))
|
|
|
|
// TODO: CHECK CAR IS ON
|
|
// TODO: Check that the salt or session matches
|
|
// Check that the QR code is valid and from the car
|
|
logs.add(fmt.Sprintf("VehicleExternalDriverAdd: Validating connection info\nVIN: %s\nSalt: %s\nSessionID: %s",
|
|
vdai.PairingInfo.VIN, vdai.PairingInfo.Salt, vdai.PairingInfo.SessionID))
|
|
|
|
err = ValidateConnectionInfo(vdai.PairingInfo, logs)
|
|
if err != nil {
|
|
logs.add(fmt.Sprintf("VehicleExternalDriverAdd: Connection info validation failed\nError: %v\nStack Trace: %s\nVIN: %s\nSalt: %s\nSessionID: %s",
|
|
err, string(debug.Stack()), vdai.PairingInfo.VIN, vdai.PairingInfo.Salt, vdai.PairingInfo.SessionID))
|
|
return
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("VehicleExternalDriverAdd: Connection info validation successful\nVIN: %s", vdai.PairingInfo.VIN))
|
|
|
|
// Try to Create an account for this user. If they already have an account, that is fine as well
|
|
logs.add(fmt.Sprintf("VehicleExternalDriverAdd: Adding new driver to database\nUserID: %s\nSource: %s", vdai.UserID, vdai.Source))
|
|
|
|
userID, err := addNewDriverDatabase(vdai.UserID, vdai.Source, logs)
|
|
if err != nil {
|
|
logs.add(fmt.Sprintf("VehicleExternalDriverAdd: Failed to add new driver to database\nError: %v\nStack Trace: %s\nUserID: %s\nSource: %s",
|
|
err, string(debug.Stack()), vdai.UserID, vdai.Source))
|
|
return
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("VehicleExternalDriverAdd: Driver added to database successfully\nUserID: %s\nSource: %s\nFiskerUserID: %s", vdai.UserID, vdai.Source, userID))
|
|
|
|
// So we now have a user, we can now begin the car pairing
|
|
// Create car to driver entry
|
|
logs.add(fmt.Sprintf("VehicleExternalDriverAdd: Creating car to driver relationship\nVIN: %s\nFiskerUserID: %s", vdai.PairingInfo.VIN, userID))
|
|
|
|
cars := services.GetDB().GetCars()
|
|
relation, err := cars.AddDriver(&common.Car{VIN: vdai.PairingInfo.VIN}, &common.Driver{ID: userID}, "OWNER") // Don't know if there is any other role
|
|
|
|
if err != nil {
|
|
logs.add(fmt.Sprintf("VehicleExternalDriverAdd: Failed to create car to driver relationship\nError: %v\nStack Trace: %s\nVIN: %s\nFiskerUserID: %s\nRole: %s",
|
|
err, string(debug.Stack()), vdai.PairingInfo.VIN, userID, "OWNER"))
|
|
return
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("VehicleExternalDriverAdd: Car to driver relationship created successfully\nVIN: %s\nDriverID: %s\nDriverRole: %s", relation.VIN, relation.DriverID, relation.DriverRole))
|
|
|
|
// Send HMI command
|
|
logs.add(fmt.Sprintf("VehicleExternalDriverAdd: Getting Redis connection from pool\nVIN: %s\nDriverID: %s", relation.VIN, relation.DriverID))
|
|
|
|
conn := services.RedisClientPool().GetFromPool()
|
|
defer conn.Close()
|
|
|
|
logs.add(fmt.Sprintf("VehicleExternalDriverAdd: Preparing HMI message\nVIN: %s\nDriverID: %s\nDriverRole: %s\nFirstName: %s\nLastName: %s",
|
|
relation.VIN, relation.DriverID, relation.DriverRole, vdai.Person.FirstName, vdai.Person.LastName))
|
|
|
|
// TODO: Add settings HERE
|
|
err = conn.SafePublishMessage(
|
|
common.HMI.Key(relation.VIN),
|
|
common.Message{
|
|
Handler: "profile_new",
|
|
Data: common.JSONHMIProfile{
|
|
DriverID: relation.DriverID,
|
|
DriverRole: relation.DriverRole,
|
|
User: common.UserProfile{
|
|
FirstName: vdai.Person.FirstName,
|
|
LastName: vdai.Person.LastName,
|
|
},
|
|
Settings: make([]common.CarSetting, 0),
|
|
Subscriptions: make([]common.Subscription, 0),
|
|
},
|
|
},
|
|
)
|
|
|
|
if err != nil {
|
|
logs.add(fmt.Sprintf("VehicleExternalDriverAdd: Failed to publish HMI message\nError: %v\nStack Trace: %s\nVIN: %s\nDriverID: %s\nHMIKey: %s",
|
|
err, string(debug.Stack()), relation.VIN, relation.DriverID, common.HMI.Key(relation.VIN)))
|
|
return
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("VehicleExternalDriverAdd: HMI message published successfully\nVIN: %s\nDriverID: %s\nHMIKey: %s", relation.VIN, relation.DriverID, common.HMI.Key(relation.VIN)))
|
|
|
|
logs.add(fmt.Sprintf("VehicleExternalDriverAdd: Driver addition process completed successfully\nUserID: %s\nVIN: %s\nFiskerUserID: %s", vdai.UserID, vdai.PairingInfo.VIN, userID))
|
|
return
|
|
}
|
|
|
|
func ValidateConnectionInfo(pi PairingInfo, logs *logCollector) (err error) {
|
|
logs.add(fmt.Sprintf("ValidateConnectionInfo: Starting validation\nVIN: %s\nSalt: %s\nSessionID: %s", pi.VIN, pi.Salt, pi.SessionID))
|
|
|
|
salter, err := security.NewSalter(pi.VIN)
|
|
if err != nil {
|
|
logs.add(fmt.Sprintf("ValidateConnectionInfo: Failed to create salter\nError: %v\nStack Trace: %s\nVIN: %s", err, string(debug.Stack()), pi.VIN))
|
|
return
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("ValidateConnectionInfo: Salter created successfully\nVIN: %s", pi.VIN))
|
|
|
|
clientPool := services.GetRedisV2Client()
|
|
|
|
switch {
|
|
case pi.SessionID != "":
|
|
logs.add(fmt.Sprintf("ValidateConnectionInfo: Using session ID validation\nVIN: %s\nSessionID: %s", pi.VIN, pi.SessionID))
|
|
|
|
err = salter.ValidateSessionID(pi.SessionID)
|
|
if err != nil {
|
|
logs.add(fmt.Sprintf("ValidateConnectionInfo: Session ID validation failed\nError: %v\nStack Trace: %s\nVIN: %s\nSessionID: %s",
|
|
err, string(debug.Stack()), pi.VIN, pi.SessionID))
|
|
return
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("ValidateConnectionInfo: Session ID validation successful\nVIN: %s\nSessionID: %s", pi.VIN, pi.SessionID))
|
|
|
|
err = checkSession(clientPool, pi.VIN, pi.SessionID, logs)
|
|
if err != nil {
|
|
logs.add(fmt.Sprintf("ValidateConnectionInfo: Session check failed\nError: %v\nStack Trace: %s\nVIN: %s\nSessionID: %s",
|
|
err, string(debug.Stack()), pi.VIN, pi.SessionID))
|
|
return
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("ValidateConnectionInfo: Session validation completed successfully\nVIN: %s\nSessionID: %s", pi.VIN, pi.SessionID))
|
|
|
|
case pi.Salt != "":
|
|
logs.add(fmt.Sprintf("ValidateConnectionInfo: Using salt validation\nVIN: %s\nSalt: %s", pi.VIN, pi.Salt))
|
|
|
|
err = checkSession(clientPool, pi.VIN, pi.Salt, logs)
|
|
if err != nil {
|
|
logs.add(fmt.Sprintf("ValidateConnectionInfo: Salt check failed\nError: %v\nStack Trace: %s\nVIN: %s\nSalt: %s",
|
|
err, string(debug.Stack()), pi.VIN, pi.Salt))
|
|
return
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("ValidateConnectionInfo: Salt validation completed successfully\nVIN: %s\nSalt: %s", pi.VIN, pi.Salt))
|
|
|
|
//sessionID = salter.GenerateSessionID(pi.VIN, pi.Salt)
|
|
default:
|
|
logs.add(fmt.Sprintf("ValidateConnectionInfo: Missing both salt and session ID\nError: %v\nStack Trace: %s\nVIN: %s\nSalt: %s\nSessionID: %s",
|
|
ErrMissingSaltAndSessionID, string(debug.Stack()), pi.VIN, pi.Salt, pi.SessionID))
|
|
err = ErrMissingSaltAndSessionID
|
|
return
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("ValidateConnectionInfo: Connection info validation completed successfully\nVIN: %s", pi.VIN))
|
|
return
|
|
}
|
|
|
|
func addNewDriverDatabase(externalID, source string, logs *logCollector) (userID string, err error) {
|
|
logs.add(fmt.Sprintf("addNewDriverDatabase: Starting database operation\nExternalID: %s\nSource: %s", externalID, source))
|
|
|
|
// This complicated query does the following things
|
|
// Checks to see if the external user already exists. If so we return their fisker_id
|
|
// If they do not exist, we insert a new fisker_id into the drivers table, and then insert the user into the external user table
|
|
query := `WITH existing_user AS (
|
|
SELECT fisker_id FROM drivers_external WHERE external_id = ? AND source = ?
|
|
), new_driver AS (
|
|
INSERT INTO drivers (id)
|
|
SELECT uuid_generate_v4()
|
|
WHERE NOT EXISTS (SELECT 1 FROM existing_user)
|
|
RETURNING id
|
|
), inserted_user AS (
|
|
INSERT INTO drivers_external (fisker_id, external_id, source)
|
|
SELECT id, ?, ? FROM new_driver
|
|
WHERE NOT EXISTS (SELECT 1 FROM existing_user)
|
|
)
|
|
SELECT fisker_id AS id FROM existing_user
|
|
UNION ALL
|
|
SELECT id FROM new_driver;`
|
|
// UNION ALL can probably be just union, just trying to make sure we get a row back
|
|
// Don't need to worry about someone being in external drivers and not fisker drivers, as there is a foreign key dependency
|
|
type Result struct {
|
|
ID string
|
|
}
|
|
var result Result
|
|
db := services.GetDB().GetDBClient()
|
|
|
|
logs.add(fmt.Sprintf("addNewDriverDatabase: Executing database query\nExternalID: %s\nSource: %s", externalID, source))
|
|
|
|
_, err = db.GetConn().QueryOne(&result, query, externalID, source, externalID, source)
|
|
if err != nil {
|
|
logs.add(fmt.Sprintf("addNewDriverDatabase: Database query failed\nError: %v\nStack Trace: %s\nExternalID: %s\nSource: %s",
|
|
err, string(debug.Stack()), externalID, source))
|
|
return
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("addNewDriverDatabase: Database operation completed successfully\nExternalID: %s\nSource: %s\nFiskerUserID: %s", externalID, source, result.ID))
|
|
|
|
return result.ID, err
|
|
}
|
|
|
|
// TODO: Add validation to struct
|
|
type VehicleDriverAddInput struct {
|
|
UserID string `json:"user_id"` // However the user wants to be placed in
|
|
Source string `json:"source"` // Ideally from the key or token that is used to access this route, security wise
|
|
PairingInfo PairingInfo `json:"pairing_info"`
|
|
Person UserInfo `json:"user_info"`
|
|
CallbackURL string `json:"callback_url"` // Where to send the BLE key when pairing is done
|
|
}
|
|
|
|
type PairingInfo struct {
|
|
VIN string `json:"vin"`
|
|
Salt string `json:"salt"` // either salt or session is required
|
|
SessionID string `json:"session_id"`
|
|
}
|
|
|
|
type UserInfo struct {
|
|
FirstName string `json:"first_name"`
|
|
LastName string `json:"last_name"`
|
|
}
|
|
|
|
type VehicleDriverAddResponse struct {
|
|
AccessAllowed bool `json:"access_allowed"` // True if the user provided the correct QR code data to connect with the car
|
|
Error error `json:"error,omitempty"`
|
|
}
|
|
|
|
// HandleExternalDriverDelete godoc
|
|
// @Summary Remove driver from DB
|
|
// @Description Remove a drivers profile completely
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param Authorization header string false "Bearer <ID token>"
|
|
// @Param Api-Key header string false "<API token>"
|
|
// @Param data body VehicleDriverAddInput true "User INFO"
|
|
// @Router /drivers/remove_external [delete]
|
|
func HandleExternalDriverDelete(w http.ResponseWriter, r *http.Request) {
|
|
logs := newLogCollector()
|
|
defer func() {
|
|
subject := fmt.Sprintf("[OTA UPDATE] External Driver Delete Request - %s", time.Now().Format("2006-01-02 15:04:05"))
|
|
logs.send(subject)
|
|
}()
|
|
|
|
logs.add(fmt.Sprintf("HandleExternalDriverDelete: Request received\nEndpoint: /drivers/remove_external\nMethod: %s\nRemoteAddr: %s\nUserAgent: %s", r.Method, r.RemoteAddr, r.UserAgent()))
|
|
|
|
// Log request headers for debugging
|
|
logs.add(fmt.Sprintf("HandleExternalDriverDelete: Request headers\nContent-Type: %s\nContent-Length: %s\nAuthorization: %s\nApi-Key: %s",
|
|
r.Header.Get("Content-Type"), r.Header.Get("Content-Length"), r.Header.Get("Authorization"), r.Header.Get("Api-Key")))
|
|
|
|
vrddi := ExternalDriverDeleteInput{}
|
|
err := json.NewDecoder(r.Body).Decode(&vrddi)
|
|
if err != nil {
|
|
logs.add(fmt.Sprintf("HandleExternalDriverDelete: Failed to decode request body\nError: %v\nStack Trace: %s", err, string(debug.Stack())))
|
|
|
|
if loggerdataresp.BadDataErrorResp(w, err, http.StatusBadRequest) {
|
|
logs.add(fmt.Sprintf("HandleExternalDriverDelete: Returning bad request response\nStatus Code: %d", http.StatusBadRequest))
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("HandleExternalDriverDelete: Request data decoded successfully\nUserID: %s\nSource: %s", vrddi.UserID, vrddi.Source))
|
|
|
|
err = ExternalDriverDelete(vrddi, logs)
|
|
if err != nil {
|
|
logs.add(fmt.Sprintf("HandleExternalDriverDelete: ExternalDriverDelete failed\nError: %v\nStack Trace: %s\nUserID: %s\nSource: %s",
|
|
err, string(debug.Stack()), vrddi.UserID, vrddi.Source))
|
|
|
|
if loggerdataresp.BadDataErrorResp(w, err, http.StatusInternalServerError) {
|
|
logs.add(fmt.Sprintf("HandleExternalDriverDelete: Returning internal server error response\nStatus Code: %d\nError Message: %s",
|
|
http.StatusInternalServerError, err.Error()))
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("HandleExternalDriverDelete: Request completed successfully\nUserID: %s\nSource: %s", vrddi.UserID, vrddi.Source))
|
|
}
|
|
|
|
// Delete an external driver from the database
|
|
func ExternalDriverDelete(eddi ExternalDriverDeleteInput, logs *logCollector) (err error) {
|
|
logs.add(fmt.Sprintf("ExternalDriverDelete: Starting driver deletion process\nUserID: %s\nSource: %s", eddi.UserID, eddi.Source))
|
|
|
|
query := `WITH to_delete AS (
|
|
SELECT fisker_id FROM drivers_external WHERE external_id = ? AND source = ?
|
|
)
|
|
DELETE FROM drivers
|
|
WHERE id IN (SELECT fisker_id FROM to_delete)`
|
|
|
|
logs.add(fmt.Sprintf("ExternalDriverDelete: Executing database deletion query\nUserID: %s\nSource: %s", eddi.UserID, eddi.Source))
|
|
|
|
db := services.GetDB().GetDBClient()
|
|
_, err = db.GetConn().Exec(query, eddi.UserID, eddi.Source)
|
|
|
|
if err != nil {
|
|
logs.add(fmt.Sprintf("ExternalDriverDelete: Database deletion failed\nError: %v\nStack Trace: %s\nUserID: %s\nSource: %s",
|
|
err, string(debug.Stack()), eddi.UserID, eddi.Source))
|
|
return
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("ExternalDriverDelete: Driver deletion completed successfully\nUserID: %s\nSource: %s", eddi.UserID, eddi.Source))
|
|
|
|
return
|
|
}
|
|
|
|
type ExternalDriverDeleteInput struct {
|
|
UserID string `json:"user_id"` // However the user wants to be placed in
|
|
Source string `json:"source"` // Ideally from the key or token that is used to access this route, security wise
|
|
}
|
|
|
|
// Go here, and add function to remove a car driver relationship for an external driver
|
|
// // HandleVehicleExternalDriverDelete godoc
|
|
// // @Summary Remove driver from DB
|
|
// // @Description Remove a drivers profile completely
|
|
// // @Accept json
|
|
// // @Produce json
|
|
// @Param Authorization header string false "Bearer <ID token>"
|
|
// // @Param Api-Key header string false "<API token>"
|
|
// // @Param data body VehicleDriverAddInput true "User INFO"
|
|
// // @Router /drivers/remove_external [delete]
|
|
// func HandleVehicleExternalDriverVehicleRemove(w http.ResponseWriter, r *http.Request) {
|
|
// vrddi := VehicleExternalDriverDeleteInput{}
|
|
// err := json.NewDecoder(r.Body).Decode(&vrddi)
|
|
// if loggerdataresp.BadDataErrorResp(w, err, http.StatusBadRequest) {
|
|
// return
|
|
// }
|
|
|
|
// err = VehicleExternalDriverRemove(vrddi)
|
|
// if loggerdataresp.BadDataErrorResp(w, err, http.StatusInternalServerError) {
|
|
// return
|
|
// }
|
|
// }
|
|
|
|
// func VehicleExternalDriverRemove(vrddi VehicleExternalDriverDeleteInput) (err error) {
|
|
// query := ``
|
|
|
|
// return
|
|
// }
|
|
|
|
// type VehicleExternalDriverDeleteInput struct{
|
|
// UserID string `json:"user_id"` // However the user wants to be placed in
|
|
// Source string `json:"source"` // Ideally from the key or token that is used to access this route, security wise
|
|
// }
|
|
|
|
func checkSession(redisClient *redisv2.Connection, vin string, sessionID string, logs *logCollector) error {
|
|
logs.add(fmt.Sprintf("checkSession: Starting session validation\nVIN: %s\nSessionID: %s", vin, sessionID))
|
|
|
|
if sessionID == "" {
|
|
logs.add(fmt.Sprintf("checkSession: Session ID is empty\nError: %v\nStack Trace: %s\nVIN: %s", ErrMissingSaltAndSessionID, string(debug.Stack()), vin))
|
|
return ErrMissingSaltAndSessionID
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("checkSession: Getting session from Redis\nVIN: %s\nSessionID: %s\nRedisKey: %s", vin, sessionID, redisv2.HMISessionKey(vin)))
|
|
|
|
redisResponse := redisClient.Client.Get(context.Background(), redisv2.HMISessionKey(vin))
|
|
session, err := redisResponse.Result()
|
|
if err != nil {
|
|
logs.add(fmt.Sprintf("checkSession: Failed to get session from Redis\nError: %v\nStack Trace: %s\nVIN: %s\nSessionID: %s\nRedisKey: %s",
|
|
err, string(debug.Stack()), vin, sessionID, redisv2.HMISessionKey(vin)))
|
|
return err
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("checkSession: Retrieved session from Redis\nVIN: %s\nSessionID: %s\nRedisSession: %s", vin, sessionID, session))
|
|
|
|
if session != sessionID {
|
|
logs.add(fmt.Sprintf("checkSession: Session mismatch detected\nError: %v\nStack Trace: %s\nVIN: %s\nSessionID: %s\nRedisSession: %s",
|
|
ErrSessionMismatch, string(debug.Stack()), vin, sessionID, session))
|
|
return ErrSessionMismatch
|
|
}
|
|
|
|
logs.add(fmt.Sprintf("checkSession: Session validation completed successfully\nVIN: %s\nSessionID: %s", vin, sessionID))
|
|
|
|
return nil
|
|
}
|
|
|
|
var ErrSessionMismatch = errors.New("sessions do not match")
|
|
var ErrMissingSaltAndSessionID = errors.New("request missing salt and sessionID")
|