diff --git a/src/lib/interfaces/IDeviceService.ts b/src/lib/interfaces/IDeviceService.ts index 9b14d18f..98c14a7e 100644 --- a/src/lib/interfaces/IDeviceService.ts +++ b/src/lib/interfaces/IDeviceService.ts @@ -5,51 +5,51 @@ import type { DeviceWithJoins } from '../repositories/DeviceRepository'; * Service interface for device operations */ export interface IDeviceService { - /** - * Get a device by its EUI - * @param devEui The device EUI - */ - getDeviceByEui(devEui: string): Promise; - - /** - * Get a device with its type information - * @param devEui The device EUI - */ - getDeviceWithTypeByEui(devEui: string): Promise; - - /** - * Get all devices - */ - getAllDevices(): Promise; - - /** - * Get devices by location ID - * @param locationId The location ID - */ - getDevicesByLocation(locationId: number): Promise; - - /** - * Get devices by type ID - * @param typeId The device type ID - */ - getDevicesByType(typeId: number): Promise; - - /** - * Create a new device - * @param device The device to create - */ - createDevice(device: DeviceInsert): Promise; - - /** - * Update an existing device - * @param devEui The device EUI - * @param device The device with updated values - */ - updateDevice(devEui: string, device: DeviceUpdate): Promise; - - /** - * Delete a device - * @param devEui The device EUI - */ - deleteDevice(devEui: string): Promise; -} \ No newline at end of file + /** + * Get a device by its EUI + * @param devEui The device EUI + */ + getDeviceByEui(devEui: string): Promise; + + /** + * Get a device with its type information + * @param devEui The device EUI + */ + getDeviceWithTypeByEui(devEui: string): Promise; + + /** + * Get all devices + */ + getAllDevices(user_id: string): Promise; + + /** + * Get devices by location ID + * @param locationId The location ID + */ + getDevicesByLocation(locationId: number): Promise; + + /** + * Get devices by type ID + * @param typeId The device type ID + */ + getDevicesByType(typeId: number): Promise; + + /** + * Create a new device + * @param device The device to create + */ + createDevice(device: DeviceInsert): Promise; + + /** + * Update an existing device + * @param devEui The device EUI + * @param device The device with updated values + */ + updateDevice(devEui: string, device: DeviceUpdate): Promise; + + /** + * Delete a device + * @param devEui The device EUI + */ + deleteDevice(devEui: string): Promise; +} diff --git a/src/lib/repositories/DeviceRepository.ts b/src/lib/repositories/DeviceRepository.ts index 93c33e50..63c7978f 100644 --- a/src/lib/repositories/DeviceRepository.ts +++ b/src/lib/repositories/DeviceRepository.ts @@ -124,6 +124,41 @@ export class DeviceRepository extends BaseRepository { return (data as Device[]) || []; } + /** + * Find a device owner entry + * @param devEui The device EUI + * @param userId The user ID + */ + async findAllDevicesByOwner(userId: string): Promise { + // 1) Owned devices (cw_devices rows) + const { data: owned, error: ownedErr } = await this.supabase + .from('cw_devices') + .select('*') + .eq('user_id', userId); + + if (ownedErr) return null; + + // 2) Shared devices the user has perms for. + // Prefer a JOIN via the relationship so you get cw_devices rows directly. + // Assumes a FK cw_device_owners(dev_eui) -> cw_devices(dev_eui). + const { data: shared, error: sharedErr } = await this.supabase + .from('cw_device_owners') + .select('cw_devices(*)') // returns rows shaped like { cw_devices: Device } + .eq('user_id', userId) + .lte('permission_level', 3); // pl <= 3 as per your policy + + if (sharedErr) return null; + + // Flatten shared to Device[] + const sharedDevices: Device[] = (shared ?? []).map((r: any) => r.cw_devices).filter(Boolean); + + // Merge & dedupe by dev_eui + const byDevEui = new Map(); + for (const d of [...(owned ?? []), ...sharedDevices]) byDevEui.set(d.dev_eui, d); + + return Array.from(byDevEui.values()); + } + /** * Find a device owner entry * @param devEui The device EUI diff --git a/src/lib/services/DeviceService.ts b/src/lib/services/DeviceService.ts index 8ef84c8b..6bc337eb 100644 --- a/src/lib/services/DeviceService.ts +++ b/src/lib/services/DeviceService.ts @@ -32,8 +32,10 @@ export class DeviceService implements IDeviceService { /** * Get all devices */ - async getAllDevices(): Promise { - return this.deviceRepository.findAll(); + async getAllDevices(user_id: string): Promise { + const devices = this.deviceRepository.findAllDevicesByOwner(user_id); + + return devices; } /** diff --git a/src/routes/app/all-devices/+page.server.ts b/src/routes/app/all-devices/+page.server.ts index fee8ac43..a1d9b485 100644 --- a/src/routes/app/all-devices/+page.server.ts +++ b/src/routes/app/all-devices/+page.server.ts @@ -15,7 +15,15 @@ export const load: PageServerLoad = async ({ locals: { supabase } }) => { const errorHandler = new ErrorHandlingService(); const deviceRepository = new DeviceRepository(supabase, errorHandler); const deviceService = new DeviceService(deviceRepository); - const allDevicesPromise = deviceService.getAllDevices(); + const allDevicesNoPerm = await deviceService.getAllDevices(user.id); + if (!allDevicesNoPerm) { + throw fail(500, { message: 'Could not fetch devices' }); + } + + // Double check the user only gets their own devices + const allDevicesPromise = allDevicesNoPerm.filter((d) => d.user_id && d.user_id === user.id); + + // If you still want `allDevices` in the page, return both: return { allDevicesPromise }; }; diff --git a/static/build-info.json b/static/build-info.json index d4d7258f..001d9d85 100644 --- a/static/build-info.json +++ b/static/build-info.json @@ -1,9 +1,9 @@ { - "commit": "38664e2", + "commit": "283f16e", "branch": "style-fixes", "author": "Kevin Cantrell", - "date": "2025-09-16T08:35:24.572Z", + "date": "2025-09-18T01:50:29.049Z", "builder": "kevin@kevin-desktop", "ipAddress": "192.168.1.100", - "timestamp": 1758011724573 + "timestamp": 1758160229050 } diff --git a/svelte.config.js b/svelte.config.js index 1ee3c6cd..9f1ee43a 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -11,6 +11,9 @@ const config = { serviceWorker: { register: false // Let PWA plugin handle registration } + }, + vitePlugin: { + inspector: true } };