From 66a76eb0f9e8e4f4027001b7bb2eaa78d77fe224 Mon Sep 17 00:00:00 2001 From: Ishaan Dey Date: Wed, 1 May 2024 01:29:16 -0400 Subject: [PATCH] sql schema update + start share logic --- .../database/drizzle/0000_blushing_surge.sql | 18 ----- .../drizzle/0001_magenta_tenebrous.sql | 2 - .../database/drizzle/0002_rare_beyonder.sql | 1 - .../database/drizzle/meta/0000_snapshot.json | 64 ++++++++++++++--- .../database/drizzle/meta/0001_snapshot.json | 68 ++++++++++++++++++- .../database/drizzle/meta/0002_snapshot.json | 56 ++++++++++++++- .../database/drizzle/meta/0003_snapshot.json | 61 ++++++++++++++++- backend/database/drizzle/meta/_journal.json | 37 +++------- backend/database/src/index.ts | 21 +++++- backend/database/src/schema.ts | 18 ++--- frontend/app/(app)/layout.tsx | 1 + frontend/components/editor/navbar/share.tsx | 12 +++- frontend/lib/actions.ts | 17 +++++ 13 files changed, 294 insertions(+), 82 deletions(-) delete mode 100644 backend/database/drizzle/0000_blushing_surge.sql delete mode 100644 backend/database/drizzle/0001_magenta_tenebrous.sql delete mode 100644 backend/database/drizzle/0002_rare_beyonder.sql diff --git a/backend/database/drizzle/0000_blushing_surge.sql b/backend/database/drizzle/0000_blushing_surge.sql deleted file mode 100644 index 9a8b937..0000000 --- a/backend/database/drizzle/0000_blushing_surge.sql +++ /dev/null @@ -1,18 +0,0 @@ -CREATE TABLE `sandbox` ( - `id` text PRIMARY KEY NOT NULL, - `name` text NOT NULL, - `type` text NOT NULL, - `bucket` text, - `init` integer DEFAULT false, - `user_id` text NOT NULL, - FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE no action -); ---> statement-breakpoint -CREATE TABLE `user` ( - `id` text PRIMARY KEY NOT NULL, - `name` text NOT NULL, - `email` text NOT NULL -); ---> statement-breakpoint -CREATE UNIQUE INDEX `sandbox_id_unique` ON `sandbox` (`id`);--> statement-breakpoint -CREATE UNIQUE INDEX `user_id_unique` ON `user` (`id`); \ No newline at end of file diff --git a/backend/database/drizzle/0001_magenta_tenebrous.sql b/backend/database/drizzle/0001_magenta_tenebrous.sql deleted file mode 100644 index 45fb9f4..0000000 --- a/backend/database/drizzle/0001_magenta_tenebrous.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE `sandbox` DROP COLUMN `bucket`;--> statement-breakpoint -ALTER TABLE `sandbox` DROP COLUMN `init`; \ No newline at end of file diff --git a/backend/database/drizzle/0002_rare_beyonder.sql b/backend/database/drizzle/0002_rare_beyonder.sql deleted file mode 100644 index 2bae800..0000000 --- a/backend/database/drizzle/0002_rare_beyonder.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE sandbox ADD `visibility` text; \ No newline at end of file diff --git a/backend/database/drizzle/meta/0000_snapshot.json b/backend/database/drizzle/meta/0000_snapshot.json index eb3670d..aadfc3e 100644 --- a/backend/database/drizzle/meta/0000_snapshot.json +++ b/backend/database/drizzle/meta/0000_snapshot.json @@ -1,7 +1,7 @@ { "version": "5", "dialect": "sqlite", - "id": "9c09f493-3a05-496c-997e-b527c8f17cf9", + "id": "6570ba20-a672-400c-8147-7ba533784918", "prevId": "00000000-0000-0000-0000-000000000000", "tables": { "sandbox": { @@ -28,21 +28,13 @@ "notNull": true, "autoincrement": false }, - "bucket": { - "name": "bucket", + "visibility": { + "name": "visibility", "type": "text", "primaryKey": false, "notNull": false, "autoincrement": false }, - "init": { - "name": "init", - "type": "integer", - "primaryKey": false, - "notNull": false, - "autoincrement": false, - "default": false - }, "user_id": { "name": "user_id", "type": "text", @@ -115,6 +107,56 @@ "foreignKeys": {}, "compositePrimaryKeys": {}, "uniqueConstraints": {} + }, + "users_to_sandboxes": { + "name": "users_to_sandboxes", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sandboxId": { + "name": "sandboxId", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "users_to_sandboxes_userId_user_id_fk": { + "name": "users_to_sandboxes_userId_user_id_fk", + "tableFrom": "users_to_sandboxes", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "users_to_sandboxes_sandboxId_sandbox_id_fk": { + "name": "users_to_sandboxes_sandboxId_sandbox_id_fk", + "tableFrom": "users_to_sandboxes", + "tableTo": "sandbox", + "columnsFrom": [ + "sandboxId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} } }, "enums": {}, diff --git a/backend/database/drizzle/meta/0001_snapshot.json b/backend/database/drizzle/meta/0001_snapshot.json index fcbe687..bc042fe 100644 --- a/backend/database/drizzle/meta/0001_snapshot.json +++ b/backend/database/drizzle/meta/0001_snapshot.json @@ -1,8 +1,8 @@ { "version": "5", "dialect": "sqlite", - "id": "739c5df4-de1b-408b-bc8c-5783688c5297", - "prevId": "9c09f493-3a05-496c-997e-b527c8f17cf9", + "id": "9f64104a-4954-40c0-8155-17755ea0a243", + "prevId": "6570ba20-a672-400c-8147-7ba533784918", "tables": { "sandbox": { "name": "sandbox", @@ -28,6 +28,13 @@ "notNull": true, "autoincrement": false }, + "visibility": { + "name": "visibility", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, "user_id": { "name": "user_id", "type": "text", @@ -86,6 +93,13 @@ "primaryKey": false, "notNull": true, "autoincrement": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false } }, "indexes": { @@ -100,6 +114,56 @@ "foreignKeys": {}, "compositePrimaryKeys": {}, "uniqueConstraints": {} + }, + "users_to_sandboxes": { + "name": "users_to_sandboxes", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sandboxId": { + "name": "sandboxId", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "users_to_sandboxes_userId_user_id_fk": { + "name": "users_to_sandboxes_userId_user_id_fk", + "tableFrom": "users_to_sandboxes", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "users_to_sandboxes_sandboxId_sandbox_id_fk": { + "name": "users_to_sandboxes_sandboxId_sandbox_id_fk", + "tableFrom": "users_to_sandboxes", + "tableTo": "sandbox", + "columnsFrom": [ + "sandboxId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} } }, "enums": {}, diff --git a/backend/database/drizzle/meta/0002_snapshot.json b/backend/database/drizzle/meta/0002_snapshot.json index 786aa32..2156a39 100644 --- a/backend/database/drizzle/meta/0002_snapshot.json +++ b/backend/database/drizzle/meta/0002_snapshot.json @@ -1,8 +1,8 @@ { "version": "5", "dialect": "sqlite", - "id": "a2239d60-e4b8-4375-979f-bbca5539a825", - "prevId": "739c5df4-de1b-408b-bc8c-5783688c5297", + "id": "5baf10d6-7697-42ba-a11a-ee4c7bd7e91e", + "prevId": "9f64104a-4954-40c0-8155-17755ea0a243", "tables": { "sandbox": { "name": "sandbox", @@ -32,7 +32,7 @@ "name": "visibility", "type": "text", "primaryKey": false, - "notNull": true, + "notNull": false, "autoincrement": false }, "user_id": { @@ -107,6 +107,56 @@ "foreignKeys": {}, "compositePrimaryKeys": {}, "uniqueConstraints": {} + }, + "users_to_sandboxes": { + "name": "users_to_sandboxes", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sandboxId": { + "name": "sandboxId", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "users_to_sandboxes_userId_user_id_fk": { + "name": "users_to_sandboxes_userId_user_id_fk", + "tableFrom": "users_to_sandboxes", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "users_to_sandboxes_sandboxId_sandbox_id_fk": { + "name": "users_to_sandboxes_sandboxId_sandbox_id_fk", + "tableFrom": "users_to_sandboxes", + "tableTo": "sandbox", + "columnsFrom": [ + "sandboxId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} } }, "enums": {}, diff --git a/backend/database/drizzle/meta/0003_snapshot.json b/backend/database/drizzle/meta/0003_snapshot.json index 6f7eb1c..086eefe 100644 --- a/backend/database/drizzle/meta/0003_snapshot.json +++ b/backend/database/drizzle/meta/0003_snapshot.json @@ -1,8 +1,8 @@ { "version": "5", "dialect": "sqlite", - "id": "913932e8-65cf-40b9-a978-8818396234f6", - "prevId": "a2239d60-e4b8-4375-979f-bbca5539a825", + "id": "37e38b82-1494-4818-8c26-b9024cce3fa9", + "prevId": "5baf10d6-7697-42ba-a11a-ee4c7bd7e91e", "tables": { "sandbox": { "name": "sandbox", @@ -93,6 +93,13 @@ "primaryKey": false, "notNull": true, "autoincrement": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false } }, "indexes": { @@ -107,6 +114,56 @@ "foreignKeys": {}, "compositePrimaryKeys": {}, "uniqueConstraints": {} + }, + "users_to_sandboxes": { + "name": "users_to_sandboxes", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sandboxId": { + "name": "sandboxId", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "users_to_sandboxes_userId_user_id_fk": { + "name": "users_to_sandboxes_userId_user_id_fk", + "tableFrom": "users_to_sandboxes", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "users_to_sandboxes_sandboxId_sandbox_id_fk": { + "name": "users_to_sandboxes_sandboxId_sandbox_id_fk", + "tableFrom": "users_to_sandboxes", + "tableTo": "sandbox", + "columnsFrom": [ + "sandboxId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} } }, "enums": {}, diff --git a/backend/database/drizzle/meta/_journal.json b/backend/database/drizzle/meta/_journal.json index 2892d18..f56fe30 100644 --- a/backend/database/drizzle/meta/_journal.json +++ b/backend/database/drizzle/meta/_journal.json @@ -5,50 +5,29 @@ { "idx": 0, "version": "5", - "when": 1713849093097, - "tag": "0000_blushing_surge", + "when": 1714540200800, + "tag": "0000_big_rogue", "breakpoints": true }, { "idx": 1, "version": "5", - "when": 1713937589365, - "tag": "0001_magenta_tenebrous", + "when": 1714541190588, + "tag": "0001_empty_black_knight", "breakpoints": true }, { "idx": 2, "version": "5", - "when": 1714247208074, - "tag": "0002_rare_beyonder", + "when": 1714541209173, + "tag": "0002_sour_ego", "breakpoints": true }, { "idx": 3, "version": "5", - "when": 1714247272878, - "tag": "0003_silky_talos", - "breakpoints": true - }, - { - "idx": 4, - "version": "5", - "when": 1714535843677, - "tag": "0004_curved_shadow_king", - "breakpoints": true - }, - { - "idx": 5, - "version": "5", - "when": 1714536021138, - "tag": "0005_light_komodo", - "breakpoints": true - }, - { - "idx": 6, - "version": "5", - "when": 1714536446137, - "tag": "0006_clear_blue_shield", + "when": 1714541233589, + "tag": "0003_pale_overlord", "breakpoints": true } ] diff --git a/backend/database/src/index.ts b/backend/database/src/index.ts index 4a3315b..4cf8d51 100644 --- a/backend/database/src/index.ts +++ b/backend/database/src/index.ts @@ -3,7 +3,7 @@ import { drizzle } from "drizzle-orm/d1"; import { json } from "itty-router-extras"; import { ZodError, z } from "zod"; -import { user, sandbox } from "./schema"; +import { user, sandbox, usersToSandboxes } from "./schema"; import * as schema from "./schema"; import { eq } from "drizzle-orm"; @@ -88,6 +88,24 @@ export default { console.log(method); return methodNotAllowed; } + } else if (path === "/api/sandbox/share" && method === "POST") { + const shareSchema = z.object({ + sandboxId: z.string(), + email: z.string(), + }); + + const body = await request.json(); + const { sandboxId, email } = shareSchema.parse(body); + + const user = await db.query.user.findFirst({ + where: (user, { eq }) => eq(user.email, email), + }); + + if (!user) return invalidRequest; + + await db.insert(usersToSandboxes).values({ userId: user.id, sandboxId }).get(); + + return success; } else if (path === "/api/user") { if (method === "GET") { const params = url.searchParams; @@ -98,6 +116,7 @@ export default { where: (user, { eq }) => eq(user.id, id), with: { sandbox: true, + usersToSandboxes: true, }, }); return json(res ?? {}); diff --git a/backend/database/src/schema.ts b/backend/database/src/schema.ts index 89f5c38..0b10294 100644 --- a/backend/database/src/schema.ts +++ b/backend/database/src/schema.ts @@ -9,17 +9,14 @@ export const user = sqliteTable("user", { .unique(), name: text("name").notNull(), email: text("email").notNull(), + image: text("image"), }); export type User = typeof user.$inferSelect; export const userRelations = relations(user, ({ many }) => ({ - sandbox: many(sandbox, { - relationName: "author", - }), - sharedSandbox: many(sandbox, { - relationName: "sharedTo", - }), + sandbox: many(sandbox), + usersToSandboxes: many(usersToSandboxes), })); export const sandbox = sqliteTable("sandbox", { @@ -41,18 +38,15 @@ export const sandboxRelations = relations(sandbox, ({ one, many }) => ({ author: one(user, { fields: [sandbox.userId], references: [user.id], - relationName: "sandbox", - }), - sharedTo: many(user, { - relationName: "sharedSandbox", }), + usersToSandboxes: many(usersToSandboxes), })); export const usersToSandboxes = sqliteTable("users_to_sandboxes", { - userId: integer("userId") + userId: text("userId") .notNull() .references(() => user.id), - sandboxId: integer("sandboxId") + sandboxId: text("sandboxId") .notNull() .references(() => sandbox.id), }); diff --git a/frontend/app/(app)/layout.tsx b/frontend/app/(app)/layout.tsx index a191f40..8b33c07 100644 --- a/frontend/app/(app)/layout.tsx +++ b/frontend/app/(app)/layout.tsx @@ -31,6 +31,7 @@ export default async function AppAuthLayout({ console.log(res) } else { // user already exists in db + console.log("user exists already.", dbUserJSON) } return <>{children} diff --git a/frontend/components/editor/navbar/share.tsx b/frontend/components/editor/navbar/share.tsx index 4f82b30..f941c3e 100644 --- a/frontend/components/editor/navbar/share.tsx +++ b/frontend/components/editor/navbar/share.tsx @@ -30,10 +30,12 @@ import { SelectValue, } from "@/components/ui/select" import { Loader2, UserPlus, X } from "lucide-react" -import { useState } from "react" +import { useState, useTransition } from "react" import { Sandbox } from "@/lib/types" import { Button } from "@/components/ui/button" import Avatar from "@/components/ui/avatar" +import { shareSandbox } from "@/lib/actions" +import { toast } from "sonner" const formSchema = z.object({ email: z.string().email(), @@ -64,6 +66,14 @@ export default function ShareSandboxModal({ // const id = await createSandbox(sandboxData) console.log(values) + + setLoading(true) + const res = await shareSandbox(data.id, values.email) + if (!res) { + toast.error("Failed to share.") + } + + setLoading(false) } return ( diff --git a/frontend/lib/actions.ts b/frontend/lib/actions.ts index 53d65e9..0e59d5f 100644 --- a/frontend/lib/actions.ts +++ b/frontend/lib/actions.ts @@ -42,3 +42,20 @@ export async function deleteSandbox(id: string) { revalidatePath("/dashboard") } + +export async function shareSandbox(sandboxId: string, email: string) { + try { + const res = await fetch("http://localhost:8787/api/sandbox/share", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ sandboxId, email }), + }) + + revalidatePath(`/code/${sandboxId}`) + return true + } catch (err) { + return false + } +}