Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(api): event routes #1

Merged
merged 10 commits into from
Sep 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export default defineNuxtConfig({
debug: process.env.FIREBASE_APP_CHECK_DEBUG_TOKEN || isDevelopment,
provider: 'ReCaptchaEnterprise' || process.env.FIREBASE_APP_CHECK_PROVIDER,
key: '6LfNWy8oAAAAAG9GdaqR-X8t8721YyHyILD_C6Pu' || process.env.FIREBASE_APP_CHECK_KEY,
isTokenAutoRefreshEnabled: false,
isTokenAutoRefreshEnabled: true,
},
},

Expand Down
29 changes: 12 additions & 17 deletions server/api/event/[id].delete.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
import dayjs from 'dayjs'
import { eq } from 'drizzle-orm'
import { events } from '~/server/db/schema'

export default defineProtectedEventHandler(event => ({
id: event.context.params!.id,
name: 'SST Homecoming 2024',
description: 'SST Homecoming 2024',
location: 'SST',
badgeImage: 'https://www.sst.edu.sg/images/default-source/album/2019-2020/2020-01-24-homecoming/20200124_182000.jpg?sfvrsn=2',
startDateTime: dayjs(Date.now()).valueOf(),
endDateTime: dayjs(Date.now()).valueOf(),
attendees: [
{
id: '123',
name: 'Qin Guan',
admissionKey: '123',
},
],
}))
export default defineProtectedEventHandler(async (event) => {
Ethan-Chew marked this conversation as resolved.
Show resolved Hide resolved
const eventId = event.context.params!.id

await event.context.database.delete(events)
.where(eq(events.id, eventId))

return sendNoContent(event)
}, {
restrictTo: ['exco'],
})
53 changes: 37 additions & 16 deletions server/api/event/[id].get.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,39 @@
import dayjs from 'dayjs'
export default defineProtectedEventHandler(async (event) => {
const eventId = event.context.params!.id

export default defineProtectedEventHandler(event => ({
id: event.context.params!.id,
name: 'SST Homecoming 2024',
description: 'SST Homecoming 2024',
location: 'SST',
badgeImage: 'https://www.sst.edu.sg/images/default-source/album/2019-2020/2020-01-24-homecoming/20200124_182000.jpg?sfvrsn=2',
startDateTime: dayjs(Date.now()).valueOf(),
endDateTime: dayjs(Date.now()).valueOf(),
attendees: [
{
id: '123',
name: 'Qin Guan',
admissionKey: '123',
const result = await event.context.database.query.events.findFirst({
where: (events, { eq }) => eq(events.id, eventId),
with: {
usersToEvents: {
with: {
user: {
columns: {
id: true,
name: true,
},
},
},
columns: {
admissionKey: true,
},
},
},
],
}))
})

if (!result) {
throw createError({
status: 400,
statusMessage: 'Bad request',
})
}

const { usersToEvents, ...data } = result

return {
...data,
attendees: usersToEvents.map(({ admissionKey, user }) => ({
...user,
admissionKey,
})),
}
})
65 changes: 48 additions & 17 deletions server/api/event/[id].post.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,49 @@
import dayjs from 'dayjs'
import { eq } from 'drizzle-orm'
import { z } from 'zod'
import { events } from '~/server/db/schema'

export default defineProtectedEventHandler(event => ({
id: event.context.params!.id,
name: 'SST Homecoming 2024',
description: 'SST Homecoming 2024',
location: 'SST',
badgeImage: 'https://www.sst.edu.sg/images/default-source/album/2019-2020/2020-01-24-homecoming/20200124_182000.jpg?sfvrsn=2',
startDateTime: dayjs(Date.now()).valueOf(),
endDateTime: dayjs(Date.now()).valueOf(),
attendees: [
{
id: '123',
name: 'Qin Guan',
admissionKey: '123',
},
],
}))
const updateEventRequestBody = z.object({
name: z.string(),
description: z.string(),
location: z.string(),
badgeImage: z.string().url(),
startDateTime: z.string().datetime(),
endDateTime: z.string().datetime(),
})

export default defineProtectedEventHandler(async (event) => {
const eventId = event.context.params!.id

const result = await updateEventRequestBody.safeParseAsync(await readBody(event))
if (!result.success) {
throw createError({
status: 400,
statusMessage: 'Bad request',
})
}

const { data } = result

const updatedEvent = await event.context.database.update(events)
.set({
name: data.name,
description: data.description,
location: data.location,
badgeImage: data.badgeImage,
startDateTime: data.startDateTime,
endDateTime: data.endDateTime,
})
.where(eq(events.id, eventId))
.returning()

if (updatedEvent.length > 1) {
throw createError({
status: 500,
statusMessage: 'Internal server error',
})
}

return updatedEvent[0]
}, {
restrictTo: ['exco'],
})
56 changes: 39 additions & 17 deletions server/api/event/index.get.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,40 @@
import dayjs from 'dayjs'

export default defineProtectedEventHandler(event => [{
id: event.context.params!.id,
name: 'SST Homecoming 2024',
description: 'SST Homecoming 2024',
location: 'SST',
badgeImage: 'https://www.sst.edu.sg/images/default-source/album/2019-2020/2020-01-24-homecoming/20200124_182000.jpg?sfvrsn=2',
startDateTime: dayjs(Date.now()).valueOf(),
endDateTime: dayjs(Date.now()).valueOf(),
attendees: [
{
id: '123',
name: 'Qin Guan',
admissionKey: '123',
export default defineProtectedEventHandler(async (event) => {
const result = await event.context.database.query.events.findMany({
with: {
usersToEvents: {
with: {
user: {
columns: {
id: true,
name: true,
},
},
},
columns: {
admissionKey: true,
},
},
},
],
}])
})

if (!result) {
throw createError({
status: 400,
statusMessage: 'Bad request',
})
}

return result.map((item) => {
const { usersToEvents, ...data } = item

return {
...data,
attendees: usersToEvents.map(({ admissionKey, user }) => ({
...user,
admissionKey,
})),
}
})
}, {
restrictTo: ['exco'],
})
45 changes: 45 additions & 0 deletions server/api/event/index.post.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { z } from 'zod'
import { events } from '~/server/db/schema'

const createEventRequestBody = z.object({
name: z.string(),
description: z.string(),
location: z.string(),
badgeImage: z.string().url(),
startDateTime: z.string().datetime(),
endDateTime: z.string().datetime(),
})

export default defineProtectedEventHandler(async (event) => {
const result = await createEventRequestBody.safeParseAsync(await readBody(event))
if (!result.success) {
throw createError({
status: 400,
statusMessage: 'Bad request',
})
}

const { data } = result

const createdEvent = await event.context.database.insert(events)
.values({
name: data.name,
description: data.description,
location: data.location,
badgeImage: data.badgeImage,
startDateTime: data.startDateTime,
endDateTime: data.endDateTime,
})
.returning()

if (createdEvent.length > 1) {
throw createError({
status: 500,
statusMessage: 'Internal server error',
})
}

return createdEvent[0]
}, {
restrictTo: ['exco'],
})
2 changes: 1 addition & 1 deletion server/api/user/[id].delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ export default defineProtectedEventHandler(async (event) => {
eq(users.id, event.context.params!.id),
)

return { ok: true }
return sendNoContent(event)
})
2 changes: 1 addition & 1 deletion server/db/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const users = sqliteTable('users', {
})

export const events = sqliteTable('events', {
id: text('id').primaryKey(),
id: text('id').primaryKey().$defaultFn(() => createId()),
name: text('name').notNull(),
description: text('description').notNull(),
location: text('location').notNull(),
Expand Down
10 changes: 10 additions & 0 deletions server/utils/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ declare module 'h3' {
export interface DefineProtectedEventHandlerOptions {
cache?: Pick<CachedEventHandlerOptions, 'maxAge'>
allowUnlinkedUser?: boolean // Allow users which do not have a `firebaseId` linked in database
restrictTo?: Array<User['memberType']>
}

const defaultOptions: DefineProtectedEventHandlerOptions = {
Expand Down Expand Up @@ -61,6 +62,15 @@ export function defineProtectedEventHandler<T extends EventHandlerRequest, D>(
})
}

if (options.restrictTo) {
if (!user?.memberType || !options.restrictTo.includes(user.memberType)) {
throw createError({
status: 403,
statusMessage: 'Forbidden',
})
}
}

event.context.user = user
event.context.firebaseId = sub

Expand Down