diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..1d8c1b2 --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,12 @@ + + + + + postgresql + true + org.postgresql.Driver + jdbc:postgresql://localhost:5432/kidarr + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7223a27 --- /dev/null +++ b/Makefile @@ -0,0 +1,35 @@ +.PHONY: build-development +build-development: ## Build the development docker image. + docker compose -f hosting/docker/development/docker-compose.yaml build + +.PHONY: start-development +start-development: ## Start the development docker container. + docker compose -f hosting/docker/development/docker-compose.yaml up -d + +.PHONY: stop-development +stop-development: ## Stop the development docker container. + docker compose -f hosting/docker/development/docker-compose.yaml down + +.PHONY: build-staging +build-staging: ## Build the staging docker image. + docker compose -f hosting/docker/staging/docker-compose.yaml build + +.PHONY: start-staging +start-staging: ## Start the staging docker container. + docker compose -f hosting/docker/staging/docker-compose.yaml up -d + +.PHONY: stop-staging +stop-staging: ## Stop the staging docker container. + docker compose -f hosting/docker/staging/docker-compose.yaml down + +.PHONY: build-production +build-production: ## Build the production docker image. + docker compose -f hosting/docker/production/docker-compose.yaml build + +.PHONY: start-production +start-production: ## Start the production docker container. + docker compose -f hosting/docker/production/docker-compose.yaml up -d + +.PHONY: stop-production +stop-production: ## Stop the production docker container. + docker compose -f hosting/docker/production/docker-compose.yaml down diff --git a/bun.lockb b/bun.lockb index 197b162..fea657b 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/hosting/docker/development/Dockerfile b/hosting/docker/development/Dockerfile new file mode 100644 index 0000000..a2b8008 --- /dev/null +++ b/hosting/docker/development/Dockerfile @@ -0,0 +1,9 @@ +FROM oven/bun:alpine AS base + + # 1. Install dependencies only when needed +FROM base AS deps + # Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. + +WORKDIR /app +COPY package.json bun.lockb ./ +RUN bun install --frozen-lockfile diff --git a/hosting/docker/development/docker-compose.yaml b/hosting/docker/development/docker-compose.yaml new file mode 100644 index 0000000..1bfdc9b --- /dev/null +++ b/hosting/docker/development/docker-compose.yaml @@ -0,0 +1,10 @@ +version: "3" + +services: + with-docker-multi-env-development: + build: + context: ../../../ + dockerfile: hosting/docker/development/Dockerfile + image: with-docker-multi-env-development + ports: + - "3001:3000" diff --git a/package.json b/package.json index 92f1739..fb8f0c6 100644 --- a/package.json +++ b/package.json @@ -65,10 +65,11 @@ "drizzle-orm": "^0.29.3", "drizzle-zod": "^0.5.1", "embla-carousel-react": "^8.0.0-rc22", + "generate-api-key": "^1.0.2", "http-status-codes": "^2.3.0", "leaflet": "^1.9.4", "local-ssl-proxy": "^2.0.5", - "lucide-react": "^0.320.0", + "lucide-react": "^0.321.0", "next": "^14.1.0", "next-auth": "^4.24.5", "next-themes": "^0.2.1", @@ -92,14 +93,14 @@ }, "devDependencies": { "@types/eslint": "^8.44.7", - "@types/node": "^20.11.14", - "@types/react": "^18.2.37", + "@types/node": "^20.11.16", + "@types/react": "^18.2.51", "@types/react-dom": "^18.2.15", "@typescript-eslint/eslint-plugin": "^6.11.0", "@typescript-eslint/parser": "^6.11.0", "autoprefixer": "^10.4.14", "dotenv": "^16.3.2", - "drizzle-kit": "^0.20.13", + "drizzle-kit": "^0.20.14", "eslint": "^8.54.0", "eslint-config-next": "^14.0.4", "pg": "^8.11.3", diff --git a/scripts/reset.sh b/scripts/reset.sh index 0f360a8..f75cbf2 100755 --- a/scripts/reset.sh +++ b/scripts/reset.sh @@ -7,12 +7,10 @@ echo Removing migrations rm -rf drizzle echo "Dropping db" -if $NODE_NEV ne "production"; then - echo "Dropping production db" - dropdb -f --if-exists kidarr - echo "Creating production db" - createdb kidarr -fi +echo "Dropping production db" +dropdb -f --if-exists kidarr +echo "Creating production db" +createdb kidarr bun db:generate bun db:migrate diff --git a/src/app/api/device/connect/route.ts b/src/app/api/device/connect/route.ts new file mode 100644 index 0000000..8f4a0df --- /dev/null +++ b/src/app/api/device/connect/route.ts @@ -0,0 +1,37 @@ +import { getChildById } from "@/lib/api/children/queries"; +import { badRequest } from "@/lib/api/responses"; +import { createApiKey } from "@/lib/services/auth/api-key"; +import { createDevice } from "@/lib/api/devices/mutations"; + +type DeviceConnectRequest = { + deviceId: string; + childId: string; + deviceName: string; +}; +const POST = async (req: Request, res: Response) => { + if (req.method !== "POST") { + return badRequest("Invalid method"); + } + + const { deviceId, childId, deviceName } = + (await req.json()) as DeviceConnectRequest; + + if (!deviceId || !childId || !deviceName) { + return badRequest("Invalid request"); + } + + const child = (await getChildById(childId)).child; + + if (!child) { + return badRequest("Invalid child"); + } + + const apiKey = createApiKey(); + + await createDevice({ + childId: child.id, + deviceId: deviceId, + name: deviceName, + apiKey: apiKey, + }); +}; diff --git a/src/components/maps/map-marker.tsx b/src/components/maps/map-marker.tsx index 36d48c3..d09c7ac 100644 --- a/src/components/maps/map-marker.tsx +++ b/src/components/maps/map-marker.tsx @@ -84,41 +84,19 @@ const MapMarker: React.FC = ({ - {/**/} - {/* */} - {/* */} - {/* */} - {/* {getInitials(childName)}*/} - {/* */} - {/* */} - {/* */} - {/* {childName}*/} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* {deviceName}*/} - {/* */} - {/* */} - {/* */} - {/* */} - {/**/} - + {deviceName} - Last seen - {humanizeDate(timestamp)} - - - + + + - + diff --git a/src/lib/services/auth/api-key.ts b/src/lib/services/auth/api-key.ts new file mode 100644 index 0000000..a81d443 --- /dev/null +++ b/src/lib/services/auth/api-key.ts @@ -0,0 +1,6 @@ +import generateApiKey from "generate-api-key"; + +const createApiKey = () => + generateApiKey({ method: "string", length: 256 }) as string; + +export { createApiKey }; diff --git a/src/server/db/migrations/0004_lying_jack_murdock.sql b/src/server/db/migrations/0004_lying_jack_murdock.sql new file mode 100644 index 0000000..5a707a4 --- /dev/null +++ b/src/server/db/migrations/0004_lying_jack_murdock.sql @@ -0,0 +1 @@ +ALTER TABLE "devices" ADD COLUMN "api_key" varchar(256) NOT NULL; \ No newline at end of file diff --git a/src/server/db/migrations/0005_furry_doctor_octopus.sql b/src/server/db/migrations/0005_furry_doctor_octopus.sql new file mode 100644 index 0000000..a0d406b --- /dev/null +++ b/src/server/db/migrations/0005_furry_doctor_octopus.sql @@ -0,0 +1 @@ +ALTER TABLE "devices" ALTER COLUMN "api_key" SET DEFAULT 'asdsad'; \ No newline at end of file diff --git a/src/server/db/migrations/0006_wooden_next_avengers.sql b/src/server/db/migrations/0006_wooden_next_avengers.sql new file mode 100644 index 0000000..7ce7d8b --- /dev/null +++ b/src/server/db/migrations/0006_wooden_next_avengers.sql @@ -0,0 +1 @@ +ALTER TABLE "devices" ALTER COLUMN "api_key" DROP DEFAULT; \ No newline at end of file diff --git a/src/server/db/migrations/meta/0004_snapshot.json b/src/server/db/migrations/meta/0004_snapshot.json new file mode 100644 index 0000000..1bccfd9 --- /dev/null +++ b/src/server/db/migrations/meta/0004_snapshot.json @@ -0,0 +1,432 @@ +{ + "id": "8b1ceb6b-cc16-4e61-b4b3-94e34f58c637", + "prevId": "82ea1092-603e-47a9-ad4c-9ca7995afb8d", + "version": "5", + "dialect": "pg", + "tables": { + "account": { + "name": "account", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "providerAccountId": { + "name": "providerAccountId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "token_type": { + "name": "token_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_state": { + "name": "session_state", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "account_userId_user_id_fk": { + "name": "account_userId_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "account_provider_providerAccountId_pk": { + "name": "account_provider_providerAccountId_pk", + "columns": [ + "provider", + "providerAccountId" + ] + } + }, + "uniqueConstraints": {} + }, + "children": { + "name": "children", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(191)", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "avatar": { + "name": "avatar", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "children_user_id_user_id_fk": { + "name": "children_user_id_user_id_fk", + "tableFrom": "children", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "devices": { + "name": "devices", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(191)", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "api_key": { + "name": "api_key", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "device_id": { + "name": "device_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "child_id": { + "name": "child_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "devices_child_id_children_id_fk": { + "name": "devices_child_id_children_id_fk", + "tableFrom": "devices", + "tableTo": "children", + "columnsFrom": [ + "child_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "devices_user_id_user_id_fk": { + "name": "devices_user_id_user_id_fk", + "tableFrom": "devices", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "pings": { + "name": "pings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(191)", + "primaryKey": true, + "notNull": true + }, + "latitude": { + "name": "latitude", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "longitude": { + "name": "longitude", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "timestamp": { + "name": "timestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "device_id": { + "name": "device_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "pings_device_id_devices_id_fk": { + "name": "pings_device_id_devices_id_fk", + "tableFrom": "pings", + "tableTo": "devices", + "columnsFrom": [ + "device_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "pings_user_id_user_id_fk": { + "name": "pings_user_id_user_id_fk", + "tableFrom": "pings", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "session": { + "name": "session", + "schema": "", + "columns": { + "sessionToken": { + "name": "sessionToken", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_userId_user_id_fk": { + "name": "session_userId_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "emailVerified": { + "name": "emailVerified", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "verificationToken": { + "name": "verificationToken", + "schema": "", + "columns": { + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "verificationToken_identifier_token_pk": { + "name": "verificationToken_identifier_token_pk", + "columns": [ + "identifier", + "token" + ] + } + }, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/src/server/db/migrations/meta/0005_snapshot.json b/src/server/db/migrations/meta/0005_snapshot.json new file mode 100644 index 0000000..d9f4ace --- /dev/null +++ b/src/server/db/migrations/meta/0005_snapshot.json @@ -0,0 +1,433 @@ +{ + "id": "f4a26526-6eed-4f4d-a8f2-599c92ae78d7", + "prevId": "8b1ceb6b-cc16-4e61-b4b3-94e34f58c637", + "version": "5", + "dialect": "pg", + "tables": { + "account": { + "name": "account", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "providerAccountId": { + "name": "providerAccountId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "token_type": { + "name": "token_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_state": { + "name": "session_state", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "account_userId_user_id_fk": { + "name": "account_userId_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "account_provider_providerAccountId_pk": { + "name": "account_provider_providerAccountId_pk", + "columns": [ + "provider", + "providerAccountId" + ] + } + }, + "uniqueConstraints": {} + }, + "children": { + "name": "children", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(191)", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "avatar": { + "name": "avatar", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "children_user_id_user_id_fk": { + "name": "children_user_id_user_id_fk", + "tableFrom": "children", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "devices": { + "name": "devices", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(191)", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "api_key": { + "name": "api_key", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true, + "default": "'asdsad'" + }, + "device_id": { + "name": "device_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "child_id": { + "name": "child_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "devices_child_id_children_id_fk": { + "name": "devices_child_id_children_id_fk", + "tableFrom": "devices", + "tableTo": "children", + "columnsFrom": [ + "child_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "devices_user_id_user_id_fk": { + "name": "devices_user_id_user_id_fk", + "tableFrom": "devices", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "pings": { + "name": "pings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(191)", + "primaryKey": true, + "notNull": true + }, + "latitude": { + "name": "latitude", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "longitude": { + "name": "longitude", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "timestamp": { + "name": "timestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "device_id": { + "name": "device_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "pings_device_id_devices_id_fk": { + "name": "pings_device_id_devices_id_fk", + "tableFrom": "pings", + "tableTo": "devices", + "columnsFrom": [ + "device_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "pings_user_id_user_id_fk": { + "name": "pings_user_id_user_id_fk", + "tableFrom": "pings", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "session": { + "name": "session", + "schema": "", + "columns": { + "sessionToken": { + "name": "sessionToken", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_userId_user_id_fk": { + "name": "session_userId_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "emailVerified": { + "name": "emailVerified", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "verificationToken": { + "name": "verificationToken", + "schema": "", + "columns": { + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "verificationToken_identifier_token_pk": { + "name": "verificationToken_identifier_token_pk", + "columns": [ + "identifier", + "token" + ] + } + }, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/src/server/db/migrations/meta/0006_snapshot.json b/src/server/db/migrations/meta/0006_snapshot.json new file mode 100644 index 0000000..a785d71 --- /dev/null +++ b/src/server/db/migrations/meta/0006_snapshot.json @@ -0,0 +1,432 @@ +{ + "id": "58c0704d-ef7a-4d9f-8f5a-e11be0d6c96b", + "prevId": "f4a26526-6eed-4f4d-a8f2-599c92ae78d7", + "version": "5", + "dialect": "pg", + "tables": { + "account": { + "name": "account", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "providerAccountId": { + "name": "providerAccountId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "token_type": { + "name": "token_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_state": { + "name": "session_state", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "account_userId_user_id_fk": { + "name": "account_userId_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "account_provider_providerAccountId_pk": { + "name": "account_provider_providerAccountId_pk", + "columns": [ + "provider", + "providerAccountId" + ] + } + }, + "uniqueConstraints": {} + }, + "children": { + "name": "children", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(191)", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "avatar": { + "name": "avatar", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "children_user_id_user_id_fk": { + "name": "children_user_id_user_id_fk", + "tableFrom": "children", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "devices": { + "name": "devices", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(191)", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "api_key": { + "name": "api_key", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "device_id": { + "name": "device_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "child_id": { + "name": "child_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "devices_child_id_children_id_fk": { + "name": "devices_child_id_children_id_fk", + "tableFrom": "devices", + "tableTo": "children", + "columnsFrom": [ + "child_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "devices_user_id_user_id_fk": { + "name": "devices_user_id_user_id_fk", + "tableFrom": "devices", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "pings": { + "name": "pings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(191)", + "primaryKey": true, + "notNull": true + }, + "latitude": { + "name": "latitude", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "longitude": { + "name": "longitude", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "timestamp": { + "name": "timestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "device_id": { + "name": "device_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "pings_device_id_devices_id_fk": { + "name": "pings_device_id_devices_id_fk", + "tableFrom": "pings", + "tableTo": "devices", + "columnsFrom": [ + "device_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "pings_user_id_user_id_fk": { + "name": "pings_user_id_user_id_fk", + "tableFrom": "pings", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "session": { + "name": "session", + "schema": "", + "columns": { + "sessionToken": { + "name": "sessionToken", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_userId_user_id_fk": { + "name": "session_userId_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "emailVerified": { + "name": "emailVerified", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "verificationToken": { + "name": "verificationToken", + "schema": "", + "columns": { + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "verificationToken_identifier_token_pk": { + "name": "verificationToken_identifier_token_pk", + "columns": [ + "identifier", + "token" + ] + } + }, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/src/server/db/migrations/meta/_journal.json b/src/server/db/migrations/meta/_journal.json index 2a76fe3..f146b64 100644 --- a/src/server/db/migrations/meta/_journal.json +++ b/src/server/db/migrations/meta/_journal.json @@ -29,6 +29,27 @@ "when": 1706731530273, "tag": "0003_luxuriant_nightshade", "breakpoints": true + }, + { + "idx": 4, + "version": "5", + "when": 1706812885568, + "tag": "0004_lying_jack_murdock", + "breakpoints": true + }, + { + "idx": 5, + "version": "5", + "when": 1706812942062, + "tag": "0005_furry_doctor_octopus", + "breakpoints": true + }, + { + "idx": 6, + "version": "5", + "when": 1706812968116, + "tag": "0006_wooden_next_avengers", + "breakpoints": true } ] } \ No newline at end of file diff --git a/src/server/db/schema/devices.ts b/src/server/db/schema/devices.ts index 326cca7..eaf9ab6 100644 --- a/src/server/db/schema/devices.ts +++ b/src/server/db/schema/devices.ts @@ -14,6 +14,7 @@ export const devices = pgTable("devices", { .primaryKey() .$defaultFn(() => randomUUID()), name: varchar("name", { length: 256 }).notNull(), + apiKey: varchar("api_key", { length: 256 }).notNull(), deviceId: varchar("device_id", { length: 256 }).notNull(), childId: varchar("child_id", { length: 256 }) .references(() => children.id, { onDelete: "cascade" })