Files
doormile_backend/controllers/cxDeviceController.go

86 lines
2.7 KiB
Go

package controllers
import (
"strings"
"doormile/db"
"doormile/models"
"doormile/utils"
"github.com/gofiber/fiber/v2"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
// Device registration — §10 of the contract.
//
// One row per device token rather than one column on the customer. A customer
// with a phone and a tablet has to get the delivery notification on both, and
// appcustomers.device_token could only ever hold whichever registered last —
// so the older device silently stopped receiving anything.
// RegisterCxDevice records a push token for the signed-in customer.
func RegisterCxDevice(c *fiber.Ctx) error {
customerID := c.Locals("userid").(int)
var req struct {
Token string `json:"token"`
Platform string `json:"platform"`
AppVersion string `json:"appVersion"`
}
if err := c.BodyParser(&req); err != nil {
return utils.CxBadRequest(c, "We could not read that request")
}
token := strings.TrimSpace(req.Token)
if token == "" {
return utils.CxBadRequest(c, "A device token is required")
}
platform := strings.ToLower(strings.TrimSpace(req.Platform))
if platform != "android" && platform != "ios" {
platform = ""
}
device := models.CustomerDevice{
Appcustomerid: customerID,
Token: token,
Platform: platform,
Appversion: strings.TrimSpace(req.AppVersion),
Lastseenat: utils.DBNow(),
}
// A token can migrate between accounts — a shared handset, or a customer
// signing out and a second one signing in. Upserting on the token (rather
// than inserting) reassigns it, which is the only outcome that does not
// send one person's parcel updates to another person's phone.
if err := db.DB.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "token"}},
DoUpdates: clause.AssignmentColumns([]string{
"appcustomerid", "platform", "appversion", "lastseenat",
}),
}).Create(&device).Error; err != nil {
utils.Error("RegisterCxDevice: upsert failed", "customer_id", customerID, "error", err)
return utils.CxInternal(c)
}
return utils.CxOK(c, fiber.Map{"registered": true})
}
// UnregisterCxDevice drops a push token. Called on sign-out, so a signed-out
// phone stops receiving updates about a pickup it can no longer open.
func UnregisterCxDevice(c *fiber.Ctx) error {
customerID := c.Locals("userid").(int)
token := strings.TrimSpace(c.Params("token"))
if token == "" {
return utils.CxBadRequest(c, "A device token is required")
}
if err := db.DB.Where("appcustomerid = ? AND token = ?", customerID, token).
Delete(&models.CustomerDevice{}).Error; err != nil && err != gorm.ErrRecordNotFound {
utils.Error("UnregisterCxDevice: delete failed", "customer_id", customerID, "error", err)
return utils.CxInternal(c)
}
return utils.CxOK(c, fiber.Map{"registered": false})
}