From 58fbe372e22e2c3c01946de8f97b781630441fc4 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Sat, 17 Oct 2026 16:39:12 -0400 Subject: [PATCH] refactor(devices): one Devices->DeviceInfo mapper for the five hand-built copies The same pgtype unwrap-and-fill block (sync_enabled/auto_sync validity, frequency fallback, pointer timestamps) existed at five DeviceInfo construction sites, two of which also carried AuthToken. deviceToInfo(device, includeAuthToken) replaces all five; token-bearing lists pass the flag explicitly so the surface that exposes the token stays a deliberate choice. --- internal/handlers/devices.go | 132 +++++++++-------------------------- 1 file changed, 34 insertions(+), 98 deletions(-) diff --git a/internal/handlers/devices.go b/internal/handlers/devices.go index bba28b68..a54d4721 100644 --- a/internal/handlers/devices.go +++ b/internal/handlers/devices.go @@ -217,6 +217,34 @@ func (h *DeviceHandler) CheckRegistrationStatus(c *echo.Context) error { }) } +// deviceToInfo is the single Devices->DeviceInfo mapper for every +// device surface. AuthToken rides only on surfaces that deliberately +// expose it (the owner's device lists). +func deviceToInfo(device database.Devices, includeAuthToken bool) DeviceInfo { + syncEnabled := device.SyncEnabled.Bool && device.SyncEnabled.Valid + autoSync := device.AutoSync.Bool && device.AutoSync.Valid + syncFreq := int32(0) + if device.SyncFrequencyMinutes.Valid { + syncFreq = device.SyncFrequencyMinutes.Int32 + } + info := DeviceInfo{ + ID: device.ID.Bytes, + DeviceName: device.DeviceName, + DeviceType: device.DeviceType, + LastSync: &device.LastSync.Time, + LastSeen: &device.LastSeen.Time, + SyncEnabled: syncEnabled, + AutoSync: autoSync, + SyncFrequency: syncFreq, + CreatedAt: device.CreatedAt.Time, + DeviceMetadata: device.DeviceMetadata, + } + if includeAuthToken { + info.AuthToken = device.AuthToken + } + return info +} + func (h *DeviceHandler) ListDevices(c *echo.Context) error { userID := c.Get("user_id").(string) userUUID, err := uuid.Parse(userID) @@ -233,26 +261,7 @@ func (h *DeviceHandler) ListDevices(c *echo.Context) error { deviceList := make([]DeviceInfo, 0, len(devices)) for _, device := range devices { - syncEnabled := device.SyncEnabled.Bool && device.SyncEnabled.Valid - autoSync := device.AutoSync.Bool && device.AutoSync.Valid - syncFreq := int32(0) - if device.SyncFrequencyMinutes.Valid { - syncFreq = device.SyncFrequencyMinutes.Int32 - } - - deviceList = append(deviceList, DeviceInfo{ - ID: device.ID.Bytes, - DeviceName: device.DeviceName, - DeviceType: device.DeviceType, - LastSync: &device.LastSync.Time, - LastSeen: &device.LastSeen.Time, - SyncEnabled: syncEnabled, - AutoSync: autoSync, - SyncFrequency: syncFreq, - CreatedAt: device.CreatedAt.Time, - DeviceMetadata: device.DeviceMetadata, - AuthToken: device.AuthToken, - }) + deviceList = append(deviceList, deviceToInfo(device, true)) } return c.JSON(http.StatusOK, DeviceListResponse{ @@ -277,26 +286,7 @@ func (h *DeviceHandler) GetDevicesData(c *echo.Context) ([]DeviceInfo, error) { deviceList := make([]DeviceInfo, 0, len(devices)) for _, device := range devices { - syncEnabled := device.SyncEnabled.Bool && device.SyncEnabled.Valid - autoSync := device.AutoSync.Bool && device.AutoSync.Valid - syncFreq := int32(0) - if device.SyncFrequencyMinutes.Valid { - syncFreq = device.SyncFrequencyMinutes.Int32 - } - - deviceList = append(deviceList, DeviceInfo{ - ID: device.ID.Bytes, - DeviceName: device.DeviceName, - DeviceType: device.DeviceType, - LastSync: &device.LastSync.Time, - LastSeen: &device.LastSeen.Time, - SyncEnabled: syncEnabled, - AutoSync: autoSync, - SyncFrequency: syncFreq, - CreatedAt: device.CreatedAt.Time, - DeviceMetadata: device.DeviceMetadata, - AuthToken: device.AuthToken, - }) + deviceList = append(deviceList, deviceToInfo(device, true)) } return deviceList, nil @@ -329,25 +319,7 @@ func (h *DeviceHandler) GetDevice(c *echo.Context) error { return c.JSON(http.StatusForbidden, map[string]string{"error": "access denied"}) } - syncEnabled := device.SyncEnabled.Bool && device.SyncEnabled.Valid - autoSync := device.AutoSync.Bool && device.AutoSync.Valid - syncFreq := int32(0) - if device.SyncFrequencyMinutes.Valid { - syncFreq = device.SyncFrequencyMinutes.Int32 - } - - return c.JSON(http.StatusOK, DeviceInfo{ - ID: device.ID.Bytes, - DeviceName: device.DeviceName, - DeviceType: device.DeviceType, - LastSync: &device.LastSync.Time, - LastSeen: &device.LastSeen.Time, - SyncEnabled: syncEnabled, - AutoSync: autoSync, - SyncFrequency: syncFreq, - CreatedAt: device.CreatedAt.Time, - DeviceMetadata: device.DeviceMetadata, - }) + return c.JSON(http.StatusOK, deviceToInfo(device, false)) } func (h *DeviceHandler) UpdateDevice(c *echo.Context) error { @@ -421,27 +393,9 @@ func (h *DeviceHandler) UpdateDevice(c *echo.Context) error { return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to update device"}) } - syncEnabled := updatedDevice.SyncEnabled.Bool && updatedDevice.SyncEnabled.Valid - autoSync := updatedDevice.AutoSync.Bool && updatedDevice.AutoSync.Valid - syncFreq := int32(0) - if updatedDevice.SyncFrequencyMinutes.Valid { - syncFreq = updatedDevice.SyncFrequencyMinutes.Int32 // Fixed: Use actual updated value - } - return c.JSON(http.StatusOK, map[string]interface{}{ "device_updated": true, - "device": DeviceInfo{ - ID: updatedDevice.ID.Bytes, - DeviceName: updatedDevice.DeviceName, - DeviceType: updatedDevice.DeviceType, - LastSync: &updatedDevice.LastSync.Time, - LastSeen: &updatedDevice.LastSeen.Time, - SyncEnabled: syncEnabled, - AutoSync: autoSync, - SyncFrequency: syncFreq, // Now correctly returns the updated value - CreatedAt: updatedDevice.CreatedAt.Time, - DeviceMetadata: updatedDevice.DeviceMetadata, - }, + "device": deviceToInfo(updatedDevice, false), }) } @@ -518,13 +472,6 @@ func (h *DeviceHandler) RegenerateDeviceToken(c *echo.Context) error { } // Return new token with device info - syncEnabled := updatedDevice.SyncEnabled.Bool && updatedDevice.SyncEnabled.Valid - autoSync := updatedDevice.AutoSync.Bool && updatedDevice.AutoSync.Valid - syncFreq := int32(0) - if updatedDevice.SyncFrequencyMinutes.Valid { - syncFreq = updatedDevice.SyncFrequencyMinutes.Int32 - } - // Build sync URLs with new token syncURLs := map[string]string{} baseURL := h.cfg.BaseURL @@ -549,19 +496,8 @@ func (h *DeviceHandler) RegenerateDeviceToken(c *echo.Context) error { return c.JSON(http.StatusOK, map[string]interface{}{ "message": "Token regenerated successfully", "auth_token": newToken, - "device": DeviceInfo{ - ID: updatedDevice.ID.Bytes, - DeviceName: updatedDevice.DeviceName, - DeviceType: updatedDevice.DeviceType, - LastSync: &updatedDevice.LastSync.Time, - LastSeen: &updatedDevice.LastSeen.Time, - SyncEnabled: syncEnabled, - AutoSync: autoSync, - SyncFrequency: syncFreq, - CreatedAt: updatedDevice.CreatedAt.Time, - DeviceMetadata: updatedDevice.DeviceMetadata, - }, - "sync_urls": syncURLs, + "device": deviceToInfo(updatedDevice, false), + "sync_urls": syncURLs, }) }