Cleanup ping route

This commit is contained in:
Fergal Moran
2024-01-30 15:39:42 +00:00
parent bfcca32221
commit f03bf48032
6 changed files with 64 additions and 55 deletions

View File

@@ -1 +1,3 @@
select * From pings --select * From pings
SELECT * FROM children ORDER BY Id DESC

View File

@@ -1,19 +1,30 @@
import { db } from "@/server/db/index"; import { db } from "@/server/db/index";
import { eq, and } from "drizzle-orm"; import { eq, and } from "drizzle-orm";
import { getUserAuth } from "@/lib/auth/utils"; import { getUserAuth } from "@/lib/auth/utils";
import { type DeviceId, deviceIdSchema, devices } from "@/server/db/schema/devices"; import {
type DeviceId,
deviceIdSchema,
devices,
} from "@/server/db/schema/devices";
import { children } from "@/server/db/schema/children"; import { children } from "@/server/db/schema/children";
export const getDevices = async () => { export const getDevices = async () => {
const { session } = await getUserAuth(); const { session } = await getUserAuth();
const d = await db.select({ device: devices, child: children }).from(devices).leftJoin(children, eq(devices.childId, children.id)).where(eq(devices.userId, session?.user.id!)); const d = await db
.select({ device: devices, child: children })
.from(devices)
.leftJoin(children, eq(devices.childId, children.id))
.where(eq(devices.userId, session?.user.id!));
return { devices: d }; return { devices: d };
}; };
export const getDeviceById = async (id: DeviceId) => { export const getDeviceById = async (id: DeviceId) => {
const { session } = await getUserAuth(); const { session } = await getUserAuth();
const { id: deviceId } = deviceIdSchema.parse({ id }); const { id: deviceId } = deviceIdSchema.parse({ id });
const [d] = await db.select().from(devices).where(and(eq(devices.id, deviceId), eq(devices.userId, session?.user.id!))).leftJoin(children, eq(devices.childId, children.id)); const [d] = await db
.select()
.from(devices)
.where(and(eq(devices.id, deviceId), eq(devices.userId, session?.user.id!)))
// .leftJoin(children, eq(devices.childId, children.id));
return { device: d }; return { device: d };
}; };

View File

@@ -1,21 +1,24 @@
import { db } from "@/server/db/index"; import { db } from "@/server/db/index";
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import { import {
PingId, type PingId,
NewPingParams, type NewPingParams,
UpdatePingParams, type UpdatePingParams,
updatePingSchema, updatePingSchema,
insertPingSchema, insertPingSchema,
pings, pings,
pingIdSchema pingIdSchema,
} from "@/server/db/schema/pings"; } from "@/server/db/schema/pings";
import { getUserAuth } from "@/lib/auth/utils"; import { getUserAuth } from "@/lib/auth/utils";
export const createPing = async (ping: NewPingParams) => { export const createPing = async (ping: NewPingParams) => {
const { session } = await getUserAuth(); const { session } = await getUserAuth();
const newPing = insertPingSchema.parse({ ...ping, userId: session?.user.id! }); const newPing = insertPingSchema.parse({
...ping,
userId: session?.user.id!,
});
try { try {
const [p] = await db.insert(pings).values(newPing).returning(); const [p] = await db.insert(pings).values(newPing).returning();
return { ping: p }; return { ping: p };
} catch (err) { } catch (err) {
const message = (err as Error).message ?? "Error, please try again"; const message = (err as Error).message ?? "Error, please try again";
@@ -27,13 +30,16 @@ export const createPing = async (ping: NewPingParams) => {
export const updatePing = async (id: PingId, ping: UpdatePingParams) => { export const updatePing = async (id: PingId, ping: UpdatePingParams) => {
const { session } = await getUserAuth(); const { session } = await getUserAuth();
const { id: pingId } = pingIdSchema.parse({ id }); const { id: pingId } = pingIdSchema.parse({ id });
const newPing = updatePingSchema.parse({ ...ping, userId: session?.user.id! }); const newPing = updatePingSchema.parse({
...ping,
userId: session?.user.id!,
});
try { try {
const [p] = await db const [p] = await db
.update(pings) .update(pings)
.set(newPing) .set(newPing)
.where(and(eq(pings.id, pingId!), eq(pings.userId, session?.user.id!))) .where(and(eq(pings.id, pingId), eq(pings.userId, session?.user.id!)))
.returning(); .returning();
return { ping: p }; return { ping: p };
} catch (err) { } catch (err) {
const message = (err as Error).message ?? "Error, please try again"; const message = (err as Error).message ?? "Error, please try again";
@@ -46,8 +52,10 @@ export const deletePing = async (id: PingId) => {
const { session } = await getUserAuth(); const { session } = await getUserAuth();
const { id: pingId } = pingIdSchema.parse({ id }); const { id: pingId } = pingIdSchema.parse({ id });
try { try {
const [p] = await db.delete(pings).where(and(eq(pings.id, pingId!), eq(pings.userId, session?.user.id!))) const [p] = await db
.returning(); .delete(pings)
.where(and(eq(pings.id, pingId), eq(pings.userId, session?.user.id!)))
.returning();
return { ping: p }; return { ping: p };
} catch (err) { } catch (err) {
const message = (err as Error).message ?? "Error, please try again"; const message = (err as Error).message ?? "Error, please try again";
@@ -55,4 +63,3 @@ export const deletePing = async (id: PingId) => {
throw { error: message }; throw { error: message };
} }
}; };

10
src/lib/api/responses.ts Normal file
View File

@@ -0,0 +1,10 @@
import { StatusCodes } from "http-status-codes";
export const notAuthorised = () =>
new Response("Not authorised", {
status: StatusCodes.BAD_REQUEST,
});
export const badRequest = (message: string) =>
new Response(message, {
status: StatusCodes.BAD_REQUEST,
});

View File

@@ -1,10 +1,12 @@
import { db } from "@/server/db"; import { db } from "@/server/db";
import { StatusCodes } from "http-status-codes"; import { StatusCodes } from "http-status-codes";
import { ping } from "@/server/db/schema";
import { type NextApiResponseServerIo } from "@/lib/models/types/next-api-response-socket"; import { type NextApiResponseServerIo } from "@/lib/models/types/next-api-response-socket";
import { badRequest, notAuthorised } from "@/app/api/responses";
import { type NextApiRequest } from "next"; import { type NextApiRequest } from "next";
import type LocationUpdate from "@/lib/models/location-update"; import type LocationUpdate from "@/lib/models/location-update";
import { badRequest, notAuthorised } from "@/lib/api/responses";
import { getDeviceById } from "@/lib/api/devices/queries";
import { getChildById } from "@/lib/api/children/queries";
import { createPing } from "@/lib/api/pings/mutations";
type PingRequest = { type PingRequest = {
coordinates: { coordinates: {
@@ -27,26 +29,12 @@ export default async function POST(
return notAuthorised(); return notAuthorised();
} }
const device = await db.query.device.findFirst({ const device = (await getDeviceById(deviceId)).device;
where: (device, { and, eq }) =>
and(eq(device.deviceId, deviceId), eq(device.apiKey, apiKey)),
});
if (!device) { if (!device) {
return notAuthorised(); return notAuthorised();
} }
const child = await db.query.child.findFirst({
where: (child, { eq }) => eq(child.id, device.childId),
});
if (!child) {
return notAuthorised();
}
const user = await db.query.users.findFirst({
where: (user, { eq }) => eq(user.id, child.parentId),
});
const { coordinates } = req.body as PingRequest; const { coordinates } = req.body as PingRequest;
// Check if coordinates exist in the headers // Check if coordinates exist in the headers
@@ -54,23 +42,14 @@ export default async function POST(
return badRequest("Invalid coordinates"); return badRequest("Invalid coordinates");
} }
const location = await db.insert(ping).values({ const location = await createPing({
deviceId: device.id, deviceId: device.id,
latitude: coordinates.latitude, latitude: coordinates.latitude,
longitude: coordinates.longitude, longitude: coordinates.longitude,
timestamp: new Date(),
}); });
const update: LocationUpdate = { console.log("ping-route", `ping:${device.id}`, location);
childId: child.id, res?.socket?.server?.io?.emit(`ping:${device.id}`, location);
location: {
latitude: coordinates.latitude,
longitude: coordinates.longitude,
},
date: new Date(),
};
console.log("ping-route", `ping:${device.id}`, update);
res?.socket?.server?.io?.emit(`ping:${device.id}`, update);
// Send a response // Send a response
return res.json({}); return res.json(location);
} }

View File

@@ -14,7 +14,7 @@ export const pings = pgTable("pings", {
.$defaultFn(() => randomUUID()), .$defaultFn(() => randomUUID()),
latitude: real("latitude").notNull(), latitude: real("latitude").notNull(),
longitude: real("longitude").notNull(), longitude: real("longitude").notNull(),
timestamp: timestamp("timestamp").notNull(), timestamp: timestamp("timestamp").notNull().defaultNow(),
deviceId: varchar("device_id", { length: 256 }) deviceId: varchar("device_id", { length: 256 })
.references(() => devices.id, { onDelete: "cascade" }) .references(() => devices.id, { onDelete: "cascade" })
.notNull(), .notNull(),
@@ -34,11 +34,11 @@ export const insertPingSchema = createInsertSchema(pings);
export const insertPingParams = createSelectSchema(pings, { export const insertPingParams = createSelectSchema(pings, {
latitude: z.coerce.number(), latitude: z.coerce.number(),
longitude: z.coerce.number(), longitude: z.coerce.number(),
timestamp: z.coerce.string().min(1),
deviceId: z.coerce.string().min(1), deviceId: z.coerce.string().min(1),
}).omit({ }).omit({
id: true, id: true,
userId: true, userId: true,
timestamp: true,
}); });
export const updatePingSchema = createSelectSchema(pings); export const updatePingSchema = createSelectSchema(pings);
@@ -46,10 +46,10 @@ export const updatePingSchema = createSelectSchema(pings);
export const updatePingParams = createSelectSchema(pings, { export const updatePingParams = createSelectSchema(pings, {
latitude: z.coerce.number(), latitude: z.coerce.number(),
longitude: z.coerce.number(), longitude: z.coerce.number(),
timestamp: z.coerce.string().min(1),
deviceId: z.coerce.string().min(1), deviceId: z.coerce.string().min(1),
}).omit({ }).omit({
userId: true, userId: true,
timestamp: true,
}); });
export const pingIdSchema = updatePingSchema.pick({ id: true }); export const pingIdSchema = updatePingSchema.pick({ id: true });