diff --git a/backend/src/db/schema.ts b/backend/src/db/schema.ts index 7a00485..2f99baf 100644 --- a/backend/src/db/schema.ts +++ b/backend/src/db/schema.ts @@ -7,8 +7,7 @@ import { varchar, integer, bigint, - uniqueIndex, - index, + unique, boolean, smallint, check @@ -35,15 +34,19 @@ export const articles = pgTable("articles", { id: uuid().notNull().primaryKey().defaultRandom(), name: varchar({ length: 255 }).notNull(), - article_status: articleStatusEnum().default("draft"), - author_id: uuid().notNull(), + article_status: articleStatusEnum().notNull().default("draft"), + author_id: uuid().notNull().references(() => users.id, { onDelete: "cascade" }), slug: varchar({ length: 511 }).unique().notNull(), summary: varchar({ length: 255 }).notNull(), date_created: timestamp({ mode: "date", withTimezone: true }).defaultNow().notNull(), last_edit: timestamp({ mode: "date", withTimezone: true }).defaultNow().notNull(), date_published: timestamp({ mode: "date", withTimezone: true }), -}); +}, + (table) => [{ + slugIdx: unique("no_repeat_slugs_per_author") + .on(table.author_id, table.slug) + }]); export const articleBlocks = pgTable("article_blocks", { id: uuid().notNull().primaryKey().defaultRandom(), @@ -55,22 +58,18 @@ export const articleBlocks = pgTable("article_blocks", { }, (table) => [{ - postPositionIdx: uniqueIndex("article_blocks_article_position_idx") - .on(table.article_id, table.position), - - postIdx: index("article_blocks_article_id_idx") - .on(table.article_id), + postPositionIdx: unique("no_repeat_block_position_per_article") + .on(table.article_id, table.position) }]); export const images = pgTable("images", { - id: uuid().notNull().primaryKey().defaultRandom(), + id: uuid().notNull().primaryKey().defaultRandom(), // Linked in 'content' of articleBlock with type 'image' bucket: varchar({ length: 63 }).notNull(), key: varchar({ length: 255 }).notNull(), mime_type: varchar({ length: 63 }).notNull(), height: integer().notNull(), width: integer().notNull(), bytes: bigint({ mode: "number" }).notNull(), - }); export const users = pgTable("users", { @@ -84,13 +83,13 @@ export const users = pgTable("users", { token: varchar({ length: 511 }), permissions: smallint().notNull().default(44), }, - (users) => [ + (_) => [ check("permissions lower bound", sql`users.permissions >= 0`), check("permissions upper bound", sql`users.permissions <= 77`), ] ); -export const relations = defineRelations({ articles, articleBlocks }, (r) => ({ +export const relations = defineRelations({ articles, articleBlocks, users }, (r) => ({ articles: { blocks: r.many.articleBlocks() }, diff --git a/backend/src/routes/blocks.ts b/backend/src/routes/blocks.ts index b0b5b3b..76249ec 100644 --- a/backend/src/routes/blocks.ts +++ b/backend/src/routes/blocks.ts @@ -1,9 +1,59 @@ import { drizzle } from 'drizzle-orm/node-postgres'; import { eq } from 'drizzle-orm'; -import { articles } from '../db/schema.ts'; +import { articleBlocks } from '../db/schema.ts'; import express, { Request, Response } from "express"; const db = drizzle(process.env.DATABASE_URL!); export const blocksRouter = express.Router(); -// TODO: implement +blocksRouter.get("/getAllBlocks", async (_: Request, res: Response) => { + const resp = await db.select().from(articleBlocks); + + res.json(resp); +}); + +blocksRouter.get("/getBlocks/:articleId", async (req: Request, res: Response) => { + const { articleId } = req.params; + const parsedId = Array.isArray(articleId) ? articleId[0] : articleId; + + const resp = await db.select() + .from(articleBlocks) + .where(eq(articleBlocks.article_id, parsedId)); + + res.json(resp); +}); + +blocksRouter.post("/createBlock", async (req: Request, res: Response) => { + const resp = await db + .insert(articleBlocks) + .values({ + ...req.body + }); + + res.json(resp); +}); + +blocksRouter.put("/updateBlock/:blockId", async (req: Request, res: Response) => { + const { blockId } = req.params; + const parsedId = Array.isArray(blockId) ? blockId[0] : blockId; + + const resp = await db + .update(articleBlocks) + .set({ + ...req.body + }) + .where(eq(articleBlocks.id, parsedId)); + + res.json(resp); +}); + +blocksRouter.delete("/deleteBlock/:blockId", async (req: Request, res: Response) => { + const { blockId } = req.params; + const parsedId = Array.isArray(blockId) ? blockId[0] : blockId; + + const resp = await db + .delete(articleBlocks) + .where(eq(articleBlocks.id, parsedId)); + + res.json(resp); +}); diff --git a/backend/src/routes/users.ts b/backend/src/routes/users.ts index e8f7f55..8b160d8 100644 --- a/backend/src/routes/users.ts +++ b/backend/src/routes/users.ts @@ -7,7 +7,12 @@ import { auth } from '../middleware/auth.ts'; const db = drizzle(process.env.DATABASE_URL!); export const usersRouter = express.Router(); -usersRouter.get("/getUser/:userId", auth, async (req: Request, res: Response) => { +usersRouter.get("/getUsers", async (_: Request, res: Response) => { + const resp = await db.select().from(users); + res.json(resp) +}); + +usersRouter.get("/getUser/:userId", async (req: Request, res: Response) => { const { userId } = req.params; const parsedId = Array.isArray(userId) ? userId[0] : userId; @@ -17,3 +22,38 @@ usersRouter.get("/getUser/:userId", auth, async (req: Request, res: Response) => res.json(resp); }); + +usersRouter.post("/createUser", async (req: Request, res: Response) => { + const resp = await db + .insert(users) + .values({ + ...req.body + }); + + res.json(resp); +}); + +usersRouter.delete("/deleteUser/:userId", async (req: Request, res: Response) => { + const { userId } = req.params; + const parsedId = Array.isArray(userId) ? userId[0] : userId; + + const resp = await db + .delete(users) + .where(eq(users.id, parsedId)); + + res.json(resp); +}); + +usersRouter.put("/updateUser/:userId", async (req: Request, res: Response) => { + const { userId } = req.params; + const parsedId = Array.isArray(userId) ? userId[0] : userId; + + const resp = await db + .update(users) + .set({ + ...req.body + }) + .where(eq(users.id, parsedId)); + + res.json(resp); +});