diff --git a/app/components/cartridge/CartridgeForm.vue b/app/components/cartridge/CartridgeForm.vue index aee02cc..28e256c 100644 --- a/app/components/cartridge/CartridgeForm.vue +++ b/app/components/cartridge/CartridgeForm.vue @@ -10,6 +10,7 @@ const form = ref>() const state = reactive({ user: route.params.user, content: cartridgeContents[0], + color: penColors[0], ml: cartridgeMls[0], mg: cartridgeMgs[1], }) diff --git a/app/components/cycle/CycleForm.vue b/app/components/round/RoundForm.vue similarity index 90% rename from app/components/cycle/CycleForm.vue rename to app/components/round/RoundForm.vue index 0c0c218..ac58c86 100644 --- a/app/components/cycle/CycleForm.vue +++ b/app/components/round/RoundForm.vue @@ -1,17 +1,18 @@ diff --git a/app/pages/users/index.vue b/app/pages/users/index.vue index 6db8b7c..6a5da40 100644 --- a/app/pages/users/index.vue +++ b/app/pages/users/index.vue @@ -18,7 +18,7 @@ const columns = [ { label: 'User', key: 'user' }, { label: 'Created At', key: 'createdAt' }, { label: 'Updated At', key: 'updatedAt' }, - { label: 'Pens', key: 'pens' }, + { label: 'Rounds', key: 'rounds' }, { label: 'Actions', key: 'actions' }, ] @@ -54,11 +54,7 @@ const { data: users } = await useFetch>('/api/all/user') diff --git a/app/types/models.d.ts b/app/types/models.d.ts index 6298152..fc412c2 100644 --- a/app/types/models.d.ts +++ b/app/types/models.d.ts @@ -14,18 +14,10 @@ export interface Token extends PrismaToken { } } -export interface UserCycle { - content: string // Tirzepatide - portions: number // 4 - duration: string // weekly - date: string -} - export interface UserPayload { roles?: { admin?: boolean } - cycles?: UserCycle[] } export interface User extends PrismaUser { @@ -39,16 +31,3 @@ export interface UserSession extends UserInfo { session: User cookie?: string } - -export interface Shot extends PrismaShot { - cartridge?: Cartridge -} - -export interface Cartridge extends PrismaCartridge { - pen?: Pen - shots?: Shot[] -} - -export interface Pen extends PrismaPen { - cartridge: Cartridge | null -} diff --git a/prisma/migrations/20240905080600_init/migration.sql b/prisma/migrations/20240905080600_init/migration.sql deleted file mode 100644 index f9418c3..0000000 --- a/prisma/migrations/20240905080600_init/migration.sql +++ /dev/null @@ -1,87 +0,0 @@ --- CreateTable -CREATE TABLE "cartridges" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "userId" INTEGER NOT NULL, - "content" TEXT NOT NULL, - "ml" DECIMAL NOT NULL, - "mg" DECIMAL NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - CONSTRAINT "cartridges_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "pens" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "userId" INTEGER NOT NULL, - "cartridgeId" INTEGER, - "color" TEXT NOT NULL, - "shotDay" TEXT, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - CONSTRAINT "pens_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "pens_cartridgeId_fkey" FOREIGN KEY ("cartridgeId") REFERENCES "cartridges" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "shots" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "userId" INTEGER NOT NULL, - "cartridgeId" INTEGER NOT NULL, - "units" INTEGER NOT NULL, - "date" DATETIME NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - CONSTRAINT "shots_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "shots_cartridgeId_fkey" FOREIGN KEY ("cartridgeId") REFERENCES "cartridges" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "users" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "email" TEXT NOT NULL, - "name" TEXT, - "avatar" TEXT, - "payload" TEXT NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL -); - --- CreateTable -CREATE TABLE "providers" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "userId" INTEGER NOT NULL, - "name" TEXT, - "avatar" TEXT, - "payload" TEXT NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - CONSTRAINT "providers_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "tokens" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "userId" INTEGER NOT NULL, - "hash" TEXT NOT NULL, - "source" TEXT NOT NULL, - "ip" TEXT NOT NULL, - "agent" TEXT NOT NULL, - "location" TEXT NOT NULL, - "coordinate" TEXT NOT NULL DEFAULT '30.2423 -97.7672', - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - CONSTRAINT "tokens_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateIndex -CREATE UNIQUE INDEX "pens_cartridgeId_key" ON "pens"("cartridgeId"); - --- CreateIndex -CREATE UNIQUE INDEX "users_email_key" ON "users"("email"); - --- CreateIndex -CREATE UNIQUE INDEX "providers_userId_name_key" ON "providers"("userId", "name"); - --- CreateIndex -CREATE UNIQUE INDEX "tokens_hash_key" ON "tokens"("hash"); diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml deleted file mode 100644 index e5e5c47..0000000 --- a/prisma/migrations/migration_lock.toml +++ /dev/null @@ -1,3 +0,0 @@ -# Please do not edit this file manually -# It should be added in your version-control system (i.e. Git) -provider = "sqlite" \ No newline at end of file diff --git a/prisma/schema/meds.prisma b/prisma/schema/meds.prisma index 966ebab..a72fb85 100644 --- a/prisma/schema/meds.prisma +++ b/prisma/schema/meds.prisma @@ -1,42 +1,16 @@ -model Cartridge { +model Round { id Int @id @default(autoincrement()) userId Int user User @relation(fields: [userId], references: [id]) content String ml Decimal mg Decimal - shots Shot[] - pen Pen? + color String + frequency String + duration String + portions Int createdAt DateTime @default(now()) updatedAt DateTime @updatedAt - @@map("cartridges") -} - -model Pen { - id Int @id @default(autoincrement()) - user User @relation(fields: [userId], references: [id]) - userId Int - cartridge Cartridge? @relation(fields: [cartridgeId], references: [id], onDelete: Restrict) - cartridgeId Int? @unique - color String - shotDay String? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - @@map("pens") -} - -model Shot { - id Int @id @default(autoincrement()) - userId Int - user User @relation(fields: [userId], references: [id]) - cartridgeId Int - cartridge Cartridge @relation(fields: [cartridgeId], references: [id], onDelete: Cascade, onUpdate: Cascade) - units Int - date DateTime - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - @@map("shots") -} + @@map("rounds") +} \ No newline at end of file diff --git a/prisma/schema/user.prisma b/prisma/schema/user.prisma index 5219d80..13fbe5e 100644 --- a/prisma/schema/user.prisma +++ b/prisma/schema/user.prisma @@ -5,9 +5,7 @@ model User { avatar String? providers Provider[] sessions Token[] - pens Pen[] - cartridges Cartridge[] - shots Shot[] + rounds Round[] payload String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@ -38,7 +36,6 @@ model Token { ip String agent String location String - // coordinate Unsupported("Point") coordinate String @default("30.2423 -97.7672") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt diff --git a/server/api/[...slug].ts b/server/api/[...slug].ts index 516869c..96253fb 100644 --- a/server/api/[...slug].ts +++ b/server/api/[...slug].ts @@ -1,11 +1,8 @@ import { createRouter, useBase } from 'h3' -import type { Cartridge, Pen, Shot, Token, User, UserCycle } from '~/types/models' -import cartridge from '../controllers/cartridge' -import cycle from '../controllers/cycle' +import type { Token, User } from '~/types/models' import logout from '../controllers/logout' import { facebookHandler, githubHandler, googleHandler, microsoftHandler } from '../controllers/oauth' -import pen from '../controllers/pen' -import shot from '../controllers/shot' +import round from '../controllers/round' import test from '../controllers/test' import token from '../controllers/token' import user from '../controllers/user' @@ -32,10 +29,7 @@ router.get('/oauth/microsoft', microsoftHandler) router.get('/logout', logout) router.apiResource<{ token: Token }>('/token', token) -router.apiResource<{ user: User, pen: Pen }>('/user/{user}/pen', pen) -router.apiResource<{ user: User, cartridge: Cartridge }>('/user/{user}/cartridge', cartridge) -router.apiResource<{ user: User, shot: Shot }>('/user/{user}/shot', shot) -router.apiResource<{ user: User, cycle: UserCycle }>('/user/{user}/cycle', cycle) +router.apiResource<{ user: User, round: Round }>('/user/{user}/pen', round) router.apiResource<{ user: User }>('/all/user', user) export default useBase('/api', router.handler) diff --git a/server/controllers/cartridge.ts b/server/controllers/cartridge.ts deleted file mode 100644 index 89126fe..0000000 --- a/server/controllers/cartridge.ts +++ /dev/null @@ -1,86 +0,0 @@ -import type { H3Event } from 'h3' -import { z } from 'zod' -import { cartridge as policies } from '../policies/cartridge' -import { include, orderBy } from '../models/cartridge' -import type { Cartridge, User } from '~/types/models' -import { cartridgeContents, cartridgeMgs, cartridgeMls } from '~/utils/shared' - -const index = async ({ user }: { user: User }, event: H3Event) => { - const { user: authed } = await requireUserSession(event) - authorize(policies.index, { authed, user }) - return metapi().render( - await usePrisma(event).cartridge.findMany({ - where: { userId: user.id }, - include, - orderBy, - }), - ) -} - -const create = async ({ user }: { user: User }, event: H3Event) => { - const { user: authed } = await requireUserSession(event) - authorize(policies.create, { authed, user }) - const schema = z.object({ - content: z.enum(cartridgeContents as [string, ...string[]]), - ml: z.enum(cartridgeMls as [string, ...string[]]), - mg: z.enum(cartridgeMgs as [string, ...string[]]), - }) - const parsed = schema.safeParse(await readBody(event)) - if (!parsed.success) return metapi().error(event, parsed.error.issues, 400) - return metapi().success('cartridge created', await usePrisma(event).cartridge.create({ - data: { - content: parsed.data.content, - ml: parsed.data.ml, - mg: parsed.data.mg, - userId: user.id, - }, - include, - })) -} - -const get = async ({ user, cartridge }: { user: User, cartridge: Cartridge }, event: H3Event) => { - const { user: authed } = await requireUserSession(event) - authorize(policies.get, { authed, user, cartridge }) - return metapi().render(cartridge) -} - -const update = async ({ user, cartridge }: { user: User, cartridge: Cartridge }, event: H3Event) => { - authorize(policies.update, { user, cartridge }) - - const schema = z.object({ - content: z.enum(cartridgeContents as [string, ...string[]]).optional(), - ml: z.enum(cartridgeMls as [string, ...string[]]).optional(), - mg: z.enum(cartridgeMgs as [string, ...string[]]).optional(), - }) - - const parsed = schema.safeParse(await readBody(event)) - if (!parsed.success) return metapi().error(event, parsed.error.issues, 400) - return metapi().success('cartridge updated', await usePrisma(event).cartridge.update({ - where: { - id: cartridge.id, - userId: user.id, - }, - data: parsed.data, - include, - })) -} - -const remove = async ({ user, cartridge }: { user: User, cartridge: Cartridge }, event: H3Event) => { - authorize(policies.remove, { user, cartridge }) - - await usePrisma(event).cartridge.delete({ - where: { - id: cartridge.id, - userId: user.id, - }, - }) - return metapi().success('cartridge deleted') -} - -export default { - index, - create, - get, - update, - remove, -} diff --git a/server/controllers/cycle.ts b/server/controllers/cycle.ts deleted file mode 100644 index cbf963d..0000000 --- a/server/controllers/cycle.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { H3Event } from 'h3' -import { z } from 'zod' -import type { User, UserCycle } from '~/types/models' -import { cartridgeContents } from '~/utils/shared' -import { cycle as policies } from '../policies/cycle' - -const create = async ({ user }: { user: User }, event: H3Event) => { - console.log('cycle.create') - const { user: authed } = await requireUserSession(event) - authorize(policies.create, { authed }) - const schema = z.object({ - content: z.enum(cartridgeContents as [string, ...string[]]), - portions: z.number(), - duration: z.string(), - date: z.string().datetime(), - }) - const parsed = schema.safeParse(await readBody(event)) - if (!parsed.success) return metapi().error(event, parsed.error.issues, 400) - - const payload = user.payload - if (!payload.cycles) - payload.cycles = [] - payload.cycles?.push(parsed.data) - - console.log('we got right before metapi().success') - return metapi().success('cycle created', await usePrisma(event).user.update({ - data: { - payload: JSON.stringify(payload), - }, - where: { - id: user.id, - }, - })) -} -const remove = async ({ user }: { user: User }, event: H3Event) => { - const { user: authed } = await requireUserSession(event) - authorize(policies.remove, { authed }) - return metapi().success('endpoint under constructino') -} - -export default { - create, - remove, -} diff --git a/server/controllers/pen.ts b/server/controllers/pen.ts deleted file mode 100644 index 685214a..0000000 --- a/server/controllers/pen.ts +++ /dev/null @@ -1,96 +0,0 @@ -import type { H3Event } from 'h3' -import { z } from 'zod' -import { pen as policies } from '../policies/pen' -import { include, orderBy } from '../models/pen' -import type { Pen, User } from '~/types/models' -import { penColors } from '~/utils/shared' - -const index = async ({ user }: { user: User }, event: H3Event) => { - const { user: authed } = await requireUserSession(event) - authorize(policies.index, { authed, user }) - return metapi().render( - await usePrisma(event).pen.findMany({ - where: { userId: user.id }, - include, - orderBy, - }), - ) -} - -const create = async ({ user }: { user: User }, event: H3Event) => { - const { user: authed } = await requireUserSession(event) - authorize(policies.create, { authed, user }) - const schema = z.object({ - color: z.enum(penColors as [string, ...string[]]), - }) - const parsed = schema.safeParse(await readBody(event)) - if (!parsed.success) return metapi().error(event, parsed.error.issues, 400) - return metapi().success('pen created', await usePrisma(event).pen.create({ - data: { - color: parsed.data.color, - userId: user.id, - cartridgeId: null, - }, - include, - })) -} - -const get = async ({ user, pen }: { user: User, pen: Pen }, event: H3Event) => { - const { user: authed } = await requireUserSession(event) - authorize(policies.get, { authed, user, pen }) - return metapi().render(pen) -} - -const update = async ({ user, pen }: { user: User, pen: Pen }, event: H3Event) => { - const { user: authed } = await requireUserSession(event) - authorize(policies.update, { authed, pen }) - - const schema = z.object({ - color: z.enum(penColors as [string, ...string[]]), - cartridgeId: z.number().optional(), - shotDay: z.string().optional(), - }) - - const body = await readBody(event) - const parsed = schema.safeParse({ - cartridgeId: Number.parseInt(body?.cartridgeId) || undefined, - color: body?.color || penColors[0], - shotDay: body?.shotDay || undefined, - }) - if (!parsed.success) return metapi().error(event, parsed.error.issues, 402) - return metapi().success('pen updated', await usePrisma(event).pen.update({ - where: { - id: pen.id, - userId: user.id, - }, - data: { - cartridgeId: parsed.data.cartridgeId ? parsed.data.cartridgeId : null, - color: parsed.data.color, - shotDay: parsed.data.shotDay || null, - }, - include, - })) -} -const remove = async ({ user, pen }: { user: User, pen: Pen }, event: H3Event) => { - const { user: authed } = await requireUserSession(event) - authorize(policies.remove, { authed, pen }) - - if (pen?.cartridgeId !== null) - return metapi().error(event, 'Cannot delete pen with cartridge', 400) - - await usePrisma(event).pen.delete({ - where: { - id: pen.id, - userId: user.id, - }, - }) - return metapi().success('pen deleted') -} - -export default { - index, - create, - get, - update, - remove, -} diff --git a/server/controllers/round.ts b/server/controllers/round.ts new file mode 100644 index 0000000..bfeb3f1 --- /dev/null +++ b/server/controllers/round.ts @@ -0,0 +1,74 @@ +import type { Round } from '@prisma/client' +import type { H3Event } from 'h3' +import { z } from 'zod' +import type { User } from '~/types/models' +import { cartridgeContents, cartridgeMgs, cartridgeMls, penColors } from '~/utils/shared' +import { include, orderBy } from '../models/round' +import { round as policies } from '../policies/round' + +const index = async ({ user }: { user: User }, event: H3Event) => { + const { user: authed } = await requireUserSession(event) + authorize(policies.index, { authed, user }) + return metapi().render( + await usePrisma(event).round.findMany({ + where: { userId: user.id }, + include, + orderBy, + }), + ) +} + +const create = async ({ user }: { user: User }, event: H3Event) => { + const { user: authed } = await requireUserSession(event) + authorize(policies.create, { authed, user }) + const schema = z.object({ + content: z.enum(cartridgeContents as [string, ...string[]]), + ml: z.enum(cartridgeMls as [string, ...string[]]), + mg: z.enum(cartridgeMgs as [string, ...string[]]), + color: z.enum(penColors as [string, ...string[]]), + frequency: z.string(), + duration: z.string(), + portions: z.number(), + }) + const parsed = schema.safeParse(await readBody(event)) + if (!parsed.success) return metapi().error(event, parsed.error.issues, 400) + return metapi().success('round created', await usePrisma(event).round.create({ + data: { + userId: user.id, + content: parsed.data.content, + ml: parsed.data.ml, + mg: parsed.data.mg, + color: parsed.data.color, + frequency: parsed.data.frequency, + duration: parsed.data.duration, + portions: parsed.data.portions, + }, + include, + })) +} + +const get = async ({ user, round }: { user: User, round: Round }, event: H3Event) => { + const { user: authed } = await requireUserSession(event) + authorize(policies.get, { authed, user, round }) + return metapi().render(round) +} + +const remove = async ({ user, round }: { user: User, round: Round }, event: H3Event) => { + const { user: authed } = await requireUserSession(event) + authorize(policies.remove, { authed, round }) + + await usePrisma(event).round.delete({ + where: { + id: round.id, + userId: user.id, + }, + }) + return metapi().success('round deleted') +} + +export default { + index, + create, + get, + remove, +} diff --git a/server/controllers/shot.ts b/server/controllers/shot.ts deleted file mode 100644 index b76985a..0000000 --- a/server/controllers/shot.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type { H3Event } from 'h3' -import { z } from 'zod' -import type { Shot, User } from '~/types/models' -import { include, orderBy } from '../models/pen' -import { shot as policies } from '../policies/shot' - -const index = async ({ user }: { user: User }, event: H3Event) => { - const { user: authed } = await requireUserSession(event) - authorize(policies.index, { authed, user }) - return metapi().render( - await usePrisma(event).shot.findMany({ - where: { - userId: user.id, - }, - orderBy, - include, - }, - ), - ) -} - -const create = async ({ user }: { user: User }, event: H3Event) => { - const { user: authed } = await requireUserSession(event) - authorize(policies.create, { authed, user }) - const schema = z.object({ - cartridgeId: z.number(), - units: z.number(), - date: z.string().datetime(), - }) - const parsed = schema.safeParse(await readBody(event)) - if (!parsed.success) return metapi().error(event, parsed.error.issues, 400) - const shot = await usePrisma(event).shot.create({ - data: { - cartridgeId: parsed.data.cartridgeId, - userId: user.id, - units: parsed.data.units, - date: new Date(parsed.data.date), - }, - include, - }) - - return metapi().success('shot logged', shot) -} - -const remove = async ({ user, shot }: { user: User, shot: Shot }, event: H3Event) => { - const { user: authed } = await requireUserSession(event) - authorize(policies.remove, { authed, shot }) - await usePrisma(event).shot.delete({ - where: { id: shot.id, userId: user.id }, - }) - return metapi().success('shot deleted') -} - -export default { - index, - create, - remove, -} diff --git a/server/models/index.ts b/server/models/index.ts index d32f4d6..6e2e990 100644 --- a/server/models/index.ts +++ b/server/models/index.ts @@ -1,13 +1,9 @@ -import * as user from './user' +import * as round from './round' import * as token from './token' -import * as pen from './pen' -import * as cartridge from './cartridge' -import * as shot from './shot' +import * as user from './user' export default { user, token, - pen, - cartridge, - shot, + round, } diff --git a/server/models/pen.ts b/server/models/pen.ts deleted file mode 100644 index 7e91d03..0000000 --- a/server/models/pen.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Prisma } from '@prisma/client' - -export const include = { - cartridge: { - include: { - shots: { - orderBy: { date: Prisma.SortOrder.asc }, - }, - }, - }, -} -export const orderBy = { - updatedAt: Prisma.SortOrder.asc, -} diff --git a/server/models/cartridge.ts b/server/models/round.ts similarity index 63% rename from server/models/cartridge.ts rename to server/models/round.ts index 636acef..7df4e12 100644 --- a/server/models/cartridge.ts +++ b/server/models/round.ts @@ -1,10 +1,7 @@ import { Prisma } from '@prisma/client' export const include = { - pen: true, - shots: { - orderBy: { date: Prisma.SortOrder.asc }, - }, + user: true, } export const orderBy = { updatedAt: Prisma.SortOrder.asc, diff --git a/server/models/shot.ts b/server/models/shot.ts deleted file mode 100644 index 0b1cd0f..0000000 --- a/server/models/shot.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Prisma } from '@prisma/client' - -export const include = { - cartridge: { - include: { - pen: true, - }, - }, -} - -export const orderBy = { - date: Prisma.SortOrder.asc, -} diff --git a/server/models/user.ts b/server/models/user.ts index e70e5a0..1257839 100644 --- a/server/models/user.ts +++ b/server/models/user.ts @@ -17,22 +17,6 @@ const payload = { }, } -const cycles = { - name: 'user.cycles', - result: { - user: { - cycles: { - needs: { - payload: true, - }, - compute({ payload }: { payload: Prisma.JsonObject }) { - return (payload as UserPayload).cycles ?? [] - }, - }, - }, - }, -} - const admin = { name: 'user.admin', result: { @@ -51,23 +35,10 @@ const admin = { } export const include = { - pens: { - include: { - cartridge: { - include: { - shots: { - include: { - cartridge: true, - }, - }, - }, - }, - }, - }, + rounds: true, } export const extend = { payload, admin, - cycles, } diff --git a/server/policies/cartridge.ts b/server/policies/cartridge.ts deleted file mode 100644 index 2d4b1a6..0000000 --- a/server/policies/cartridge.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { Cartridge, User } from '~/types/models' - -function index({ user, authed }: { user: User, authed: User }) { - return authed.isAdmin || authed.id === user.id -} - -function create({ user, authed }: { user: User, authed: User }) { - return authed.isAdmin || authed.id === user.id -} - -function get({ user, cartridge }: { user: User, cartridge: Cartridge }) { - return user.isAdmin || user.id === cartridge.userId -} - -function update({ user, cartridge }: { user: User, cartridge: Cartridge }) { - return user.isAdmin || user.id.toString() === cartridge.userId.toString() -} - -function remove({ user, cartridge }: { user: User, cartridge: Cartridge }) { - return user.isAdmin || user.id.toString() === cartridge.userId.toString() -} - -export const cartridge = { - index, - create, - get, - update, - remove, -} diff --git a/server/policies/cycle.ts b/server/policies/cycle.ts deleted file mode 100644 index eeebe80..0000000 --- a/server/policies/cycle.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { User } from '~/types/models' - -function index({ authed }: { authed: User }) { - return authed.isAdmin -} - -function create({ authed }: { authed: User }) { - return authed.isAdmin -} - -function get({ authed }: { authed: User }) { - return authed.isAdmin -} - -function update({ authed }: { authed: User }) { - return authed.isAdmin -} - -function remove({ authed }: { authed: User }) { - return authed.isAdmin -} - -export const cycle = { - index, - create, - get, - update, - remove, -} diff --git a/server/policies/pen.ts b/server/policies/pen.ts deleted file mode 100644 index c9180b3..0000000 --- a/server/policies/pen.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { Pen, User } from '~/types/models' - -function index({ user, authed }: { user: User, authed: User }) { - return authed.isAdmin || authed.id === user.id -} - -function create({ user, authed }: { user: User, authed: User }) { - return authed.isAdmin || authed.id === user.id -} - -function get({ user, pen }: { user: User, pen: Pen }) { - return user.isAdmin || user.id === pen.userId -} - -function update({ authed, pen }: { authed: User, pen: Pen }) { - return authed.isAdmin || authed.id === pen.userId -} - -function remove({ authed, pen }: { authed: User, pen: Pen }) { - return authed.isAdmin || authed.id === pen.userId -} - -export const pen = { - index, - create, - get, - update, - remove, -} diff --git a/server/policies/round.ts b/server/policies/round.ts new file mode 100644 index 0000000..eec1c80 --- /dev/null +++ b/server/policies/round.ts @@ -0,0 +1,30 @@ +import type { Round } from '@prisma/client' +import type { User } from '~/types/models' + +function index({ user, authed }: { user: User, authed: User }) { + return authed.isAdmin || authed.id === user.id +} + +function create({ user, authed }: { user: User, authed: User }) { + return authed.isAdmin || authed.id === user.id +} + +function get({ user, round }: { user: User, round: Round }) { + return user.isAdmin || user.id === round.userId +} + +function update({ authed, round }: { authed: User, round: Round }) { + return authed.isAdmin || authed.id === round.userId +} + +function remove({ authed, round }: { authed: User, round: Round }) { + return authed.isAdmin || authed.id === round.userId +} + +export const round = { + index, + create, + get, + update, + remove, +} diff --git a/server/policies/shot.ts b/server/policies/shot.ts deleted file mode 100644 index f6635f3..0000000 --- a/server/policies/shot.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { Shot, User } from '~/types/models' - -function index({ user, authed }: { user: User, authed: User }) { - return authed.isAdmin || authed.id === user.id -} - -function create({ user, authed }: { user: User, authed: User }) { - return authed.isAdmin || authed.id === user.id -} - -function get({ user, shot }: { user: User, shot: Shot }) { - return user.isAdmin || user.id === shot.userId -} - -function update({ user, shot }: { user: User, shot: Shot }) { - return user.isAdmin || user.id === shot.userId -} - -function remove({ authed, shot }: { authed: User, shot: Shot }) { - return authed.isAdmin || authed.id === shot.userId -} - -export const shot = { - index, - create, - get, - update, - remove, -} diff --git a/server/utils/prisma.ts b/server/utils/prisma.ts index ed63a34..e839600 100644 --- a/server/utils/prisma.ts +++ b/server/utils/prisma.ts @@ -1,7 +1,7 @@ -import { PrismaD1 } from '@prisma/adapter-d1' -import { PrismaClient } from '@prisma/client' import type { D1Database } from '@nuxthub/core' import type { EventHandlerRequest, H3Event } from 'h3' +import { PrismaD1 } from '@prisma/adapter-d1' +import { PrismaClient } from '@prisma/client' import models from '../models/index' export function useDB(event: H3Event): D1Database { @@ -21,7 +21,10 @@ export function usePrisma(event?: H3Event) { } if (!prismaClient) { const adapter = new PrismaD1(useDB(event)) - prismaClient = new PrismaClient({ adapter }) + prismaClient = new PrismaClient({ + adapter, + // log: ['query', 'info', 'warn', 'error'], + }) } return prismaClient .$extends(models.user.extend.payload) diff --git a/test/cartridge.test.ts b/test/cartridge.test.ts deleted file mode 100644 index 71da110..0000000 --- a/test/cartridge.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { setup } from '@nuxt/test-utils' -import { actingAs } from './auth' -import { cartridgeContents, cartridgeMgs, cartridgeMls } from '~/utils/shared' -import type { Cartridge } from '~/types/models' - -describe('/api/user/{user}/cartridge', async () => { - const cartridges: Cartridge[] = [] - await setup({ host: 'http://localhost:3000' }) - - it('post /api/user/{user}/cartridge - create a cartridge', async () => { - const { post, user } = await actingAs('test@test.com') - const { data: cartridge } = await post(`/api/user/${user.session.id}/cartridge`, { - content: cartridgeContents[0], - ml: cartridgeMls[0], - mg: cartridgeMgs[0], - }) - expect(cartridge.content).toBe(cartridgeContents[0]) - expect(`${cartridge.ml}.0`).toBe(cartridgeMls[0]) - expect(cartridge.mg).toBe(cartridgeMgs[0]) - expect(cartridge.userId).toBe(user.session.id) - cartridges.push(cartridge) - }) - - it('get /api/user/{user}/cartridge - list all cartridges', async () => { - const { get, user } = await actingAs('test@test.com') - const response = await get(`/api/user/${user.session.id}/cartridge`) - expect(response.data.find(c => c.id === cartridges[0]?.id)).toStrictEqual(cartridges[0]) - }) - - it('get /api/user/{user}/cartridge/{cartridge} - get a cartridge', async () => { - const { get, user } = await actingAs('test@test.com') - const response = await get(`/api/user/${user.session.id}/cartridge/${cartridges[0]?.id}`) - expect(response.data).toStrictEqual(cartridges[0]) - }) - - it('put /api/user/{user}/cartridge/{cartridge} - update a cartridge', async () => { - const { put, user } = await actingAs('test@test.com') - const { data: cartridge } = await put(`/api/user/${user.session.id}/cartridge/${cartridges[0]?.id}`, { - content: cartridgeContents[1], - ml: cartridgeMls[1], - mg: cartridgeMgs[1], - }) - expect(cartridge.content).toBe(cartridgeContents[1]) - expect(`${cartridge.ml}.0`).toBe(cartridgeMls[1]) - expect(cartridge.mg).toBe(cartridgeMgs[1]) - }) - - it('delete /api/user/{user}/cartridge/{cartridge} - delete a cartridge', async () => { - if (!cartridges[0]) throw new Error('Cartridge not found') - const { remove, notFound, user } = await actingAs('test@test.com') - await remove(`/api/user/${user.session.id}/cartridge/${cartridges[0]?.id}`) - expect(await notFound('GET', `/api/user/${user.session.id}/cartridge/${cartridges[0]?.id}`)).toBe(404) - }) -}) diff --git a/test/pen.test.ts b/test/pen.test.ts deleted file mode 100644 index e345e00..0000000 --- a/test/pen.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { setup } from '@nuxt/test-utils' -import { actingAs } from './auth' -import { penColors } from '~/utils/shared' -import type { Pen } from '~/types/models' - -describe('/api/user/{user}/pen', async () => { - await setup({ host: 'http://localhost:3000' }) - const pens: Pen[] = [] - - it('post /api/user/{user}/pen - create a pen', async () => { - const { post, user } = await actingAs('test@test.com') - const { data: pen } = await post(`/api/user/${user.session.id}/pen`, { color: penColors[0] }) - expect(pen.color).toBe(penColors[0]) - expect(pen.userId).toBe(user.session.id) - pens.push(pen) - }) - - it('get /api/user/{user}/pen - list all pens', async () => { - const { get, user } = await actingAs('test@test.com') - const response = await get(`/api/user/${user.session.id}/pen`) - expect(response.data.find(p => p.id === pens[0]?.id)).toStrictEqual(pens[0]) - }) - - it ('get /api/user/{user}/pen/{pen} - get a pen', async () => { - const { get, user } = await actingAs('test@test.com') - const response = await get(`/api/user/${user.session.id}/pen/${pens[0]?.id}`) - expect(response.data).toStrictEqual(pens[0]) - }) - - it ('put /api/user/{user}/pen/{pen} - update a pen', async () => { - const { put, user } = await actingAs('test@test.com') - const { data: pen } = await put(`/api/user/${user.session.id}/pen/${pens[0]?.id}`, { color: penColors[1] }) - expect(pen.color).toBe(penColors[1]) - }) - - it ('delete /api/user/{user}/pen/{pen} - delete a pen', async () => { - if (!pens[0]) throw new Error('Pen not found') - const { remove, notFound, user } = await actingAs('test@test.com') - await remove(`/api/user/${user.session.id}/pen/${pens[0]?.id}`) - expect(await notFound('GET', `/api/user/${user.session.id}/pen/${pens[0]?.id}`)).toBe(404) - }) -}) diff --git a/test/round.test.ts b/test/round.test.ts new file mode 100644 index 0000000..ebce072 --- /dev/null +++ b/test/round.test.ts @@ -0,0 +1,53 @@ +import type { Round } from '@prisma/client' +import { setup } from '@nuxt/test-utils' +import { describe, expect, it } from 'vitest' +import { cartridgeContents, cartridgeMgs, cartridgeMls, penColors } from '~/utils/shared' +import { actingAs } from './auth' + +describe('/api/user/{user}/round', async () => { + const rounds: Round[] = [] + await setup({ host: 'http://localhost:3000' }) + + it('post /api/user/{user}/round - create a round', async () => { + const { post, user } = await actingAs('test@test.com') + const { data: round } = await post(`/api/user/${user.session.id}/round`, { + content: cartridgeContents[0], + ml: cartridgeMls[0], + mg: cartridgeMgs[0], + color: penColors[0], + frequency: 'daily', + duration: '1 week', + portions: 1, + }) + expect(round.content).toBe(cartridgeContents[0]) + expect(`${round.ml}.0`).toBe(cartridgeMls[0]) + expect(round.mg).toBe(cartridgeMgs[0]) + expect(round.color).toBe(penColors[0]) + expect(round.frequency).toBe('daily') + expect(round.duration).toBe('1 week') + expect(round.portions).toBe(1) + expect(round.userId).toBe(user.session.id) + rounds.push(round) + }) + + it('get /api/user/{user}/round - list all rounds', async () => { + const { get, user } = await actingAs('test@test.com') + const response = await get(`/api/user/${user.session.id}/round`) + expect(response.data.find(c => c.id === rounds[0]?.id)).toStrictEqual(rounds[0]) + }) + + it('get /api/user/{user}/round/{round} - get a round', async () => { + const { get, user } = await actingAs('test@test.com') + const response = await get(`/api/user/${user.session.id}/round/${rounds[0]?.id}`) + expect(response.data).toStrictEqual(rounds[0]) + }) + + // Remove the 'put' test as there's no 'update' method in the controller + + it('delete /api/user/{user}/round/{round} - delete a round', async () => { + if (!rounds[0]) throw new Error('Round not found') + const { remove, notFound, user } = await actingAs('test@test.com') + await remove(`/api/user/${user.session.id}/round/${rounds[0]?.id}`) + expect(await notFound('GET', `/api/user/${user.session.id}/round/${rounds[0]?.id}`)).toBe(404) + }) +}) diff --git a/test/shot.test.ts b/test/shot.test.ts deleted file mode 100644 index 584381e..0000000 --- a/test/shot.test.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { setup } from '@nuxt/test-utils' -import { actingAs } from './auth' -import { cartridgeContents, cartridgeMgs, cartridgeMls, penColors, shotUnits } from '~/utils/shared' -import type { Cartridge, Pen, Shot } from '~/types/models' - -describe('/api/user/{user}/shot', async () => { - await setup({ host: 'http://localhost:3000' }) - - const shots: Shot[] = [] - - it('post /api/user/{user}/shot - create a shot', async () => { - const { post, put, user } = await actingAs('test@test.com') - - // Create a pen and cartridge first - const { data: pen } = await post(`/api/user/${user.session.id}/pen`, { color: penColors[0] }) - const { data: cartridge } = await post(`/api/user/${user.session.id}/cartridge`, { - content: cartridgeContents[0], - ml: cartridgeMls[0], - mg: cartridgeMgs[0], - }) - await put(`/api/user/${user.session.id}/pen/${pen.id}`, { cartridgeId: cartridge.id }) - - const { data: shot } = await post(`/api/user/${user.session.id}/shot`, { - cartridgeId: cartridge.id, - units: shotUnits[0], - date: new Date().toISOString(), - }) - expect(shot.userId).toBe(user.session.id) - expect(shot.cartridgeId).toBe(cartridge.id) - expect(shot.units).toBe(shotUnits[0]) - shots.push(shot) - }) - - it('get /api/user/{user}/shot - list all shots', async () => { - const { get, user } = await actingAs('test@test.com') - const response = await get(`/api/user/${user.session.id}/shot`) - const result = response.data.find(s => s.id === shots[0]?.id) - expect(result).toStrictEqual(shots[0]) - }) - - it ('delete /api/user/{user}/shot/{shot} - delete a shot', async () => { - if (!shots[0]) throw new Error('Shot not found') - const { remove, notFound, user } = await actingAs('test@test.com') - await remove(`/api/user/${user.session.id}/shot/${shots[0]?.id}`) - expect(await notFound('GET', `/api/user/${user.session.id}/shot/${shots[0]?.id}`)).toBe(404) - }) -})