From 49d32cff378de1417beec43f474d7867fd36a834 Mon Sep 17 00:00:00 2001 From: Peter Beverloo Date: Sun, 23 Feb 2025 16:09:22 +0000 Subject: [PATCH] perf: Record log entries after sending responses Right now, recording log entries happens while the request is being processed, and generally the response is blocked on completing the recording. This is not ideal, and Next.js v15.1's new `after()` function allows us to postpone recording the log entry until after the response has been sent. This should reduce TTFB (& subsequent metrics) with 5-10ms for each request that involves recording a log entry. --- .../[event]/hotels/HotelConfiguration.tsx | 4 +- app/admin/events/[event]/refunds/page.tsx | 4 +- .../events/[event]/settings/EventSettings.tsx | 4 +- .../training/TrainingConfiguration.tsx | 4 +- .../environments/EnvironmentSection.tsx | 4 +- .../volunteers/[id]/VolunteerPermissions.tsx | 4 +- app/api/admin/content/[[...id]]/route.ts | 6 +- .../content/categories/[[...id]]/route.ts | 4 +- app/api/admin/createEvent.ts | 4 +- app/api/admin/displays/[[...id]]/route.ts | 4 +- .../admin/event/deadlines/[[...id]]/route.ts | 4 +- app/api/admin/event/shifts/[[...id]]/route.ts | 4 +- .../shifts/categories/[[...id]]/route.ts | 4 +- app/api/admin/event/teams/[[...id]]/route.ts | 4 +- app/api/admin/exports/[[...id]]/route.ts | 4 +- app/api/admin/hotels/[[...id]]/route.ts | 4 +- .../hotels/assignments/[[...id]]/route.ts | 10 +- .../program/activities/[[...id]]/route.ts | 4 +- .../admin/program/areas/[[...id]]/route.ts | 4 +- .../program/locations/[[...id]]/route.ts | 4 +- .../admin/program/requests/[[...id]]/route.ts | 4 +- app/api/admin/refunds/[[...id]]/route.ts | 4 +- app/api/admin/resetAccessCode.ts | 4 +- app/api/admin/resetPasswordLink.ts | 4 +- app/api/admin/retention/[[...id]]/route.ts | 4 +- .../admin/retention/remindParticipation.ts | 4 +- .../admin/subscriptions/[[...id]]/route.ts | 4 +- app/api/admin/trainings/[[...id]]/route.ts | 4 +- .../trainings/assignments/[[...id]]/route.ts | 4 +- .../admin/trainings/extra/[[...id]]/route.ts | 4 +- app/api/admin/updateActivation.ts | 4 +- app/api/admin/updateEvent.ts | 8 +- app/api/admin/updateIntegration.ts | 12 +- app/api/admin/updateSettings.ts | 4 +- app/api/admin/updateTeam.ts | 4 +- app/api/admin/updateVolunteer.ts | 4 +- app/api/admin/vendors/[[...id]]/route.ts | 4 +- app/api/admin/vendors/updateVendorSchedule.ts | 4 +- app/api/admin/volunteerContactInfo.ts | 4 +- app/api/admin/volunteerRoles.tsx | 4 +- app/api/admin/volunteerTeams.ts | 4 +- .../admin/volunteers/roles/[[...id]]/route.ts | 4 +- app/api/ai/updateSettings.ts | 6 +- app/api/application/updateApplication.ts | 8 +- app/api/auth/confirmIdentity.ts | 4 +- app/api/auth/passkeys/deletePasskey.ts | 4 +- app/api/auth/passkeys/registerPasskey.ts | 4 +- app/api/auth/passwordChange.ts | 4 +- app/api/auth/passwordReset.ts | 4 +- app/api/auth/passwordResetRequest.ts | 4 +- app/api/auth/register.ts | 4 +- app/api/auth/registerActivate.ts | 4 +- app/api/auth/signInImpersonate.ts | 4 +- app/api/auth/signInPasskey.ts | 4 +- app/api/auth/signInPassword.ts | 6 +- app/api/auth/signInPasswordUpdate.ts | 4 +- app/api/auth/updateAccount.ts | 4 +- app/api/auth/updateAvatar.ts | 6 +- app/api/event/application.ts | 6 +- app/api/event/availabilityPreferences.ts | 6 +- app/api/event/hotelPreferences.ts | 8 +- app/api/event/refundRequest.ts | 8 +- app/api/event/schedule/submitFeedback.ts | 4 +- app/api/event/schedule/updateHelpRequest.ts | 6 +- app/api/event/schedule/updateNotes.ts | 4 +- app/api/event/trainingPreferences.ts | 8 +- app/api/exports/route.ts | 4 +- app/api/nardo/[[...id]]/route.ts | 4 +- app/lib/Log.ts | 63 +++- app/lib/database/Connection.ts | 4 +- app/lib/database/scheme/LogsTable.ts | 2 + ts-sql.scheme.yaml | 274 +++++++++--------- 72 files changed, 367 insertions(+), 296 deletions(-) diff --git a/app/admin/events/[event]/hotels/HotelConfiguration.tsx b/app/admin/events/[event]/hotels/HotelConfiguration.tsx index 13b88c31..013964c7 100644 --- a/app/admin/events/[event]/hotels/HotelConfiguration.tsx +++ b/app/admin/events/[event]/hotels/HotelConfiguration.tsx @@ -10,7 +10,7 @@ import { AvailabilityToggle } from '@app/admin/components/AvailabilityToggle'; import { AvailabilityWindow } from '@app/admin/components/AvailabilityWindow'; import { FormGridSection } from '@app/admin/components/FormGridSection'; import { HotelConfigurationTable } from './HotelConfigurationTable'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { SectionIntroduction } from '@app/admin/components/SectionIntroduction'; import { executeServerAction } from '@lib/serverAction'; import { getEventNameForId } from '@lib/EventLoader'; @@ -54,7 +54,7 @@ async function updateHotelConfiguration(eventId: number, formData: unknown) { .where(tEvents.eventId.equals(eventId)) .executeUpdate(); - await Log({ + RecordLog({ type: kLogType.AdminEventPublishInfo, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/admin/events/[event]/refunds/page.tsx b/app/admin/events/[event]/refunds/page.tsx index 38886abd..66731097 100644 --- a/app/admin/events/[event]/refunds/page.tsx +++ b/app/admin/events/[event]/refunds/page.tsx @@ -10,7 +10,7 @@ import type { NextPageParams } from '@lib/NextRouterParams'; import { AvailabilityToggle } from '@app/admin/components/AvailabilityToggle'; import { AvailabilityWindow } from '@app/admin/components/AvailabilityWindow'; import { FormGridSection } from '@app/admin/components/FormGridSection'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { RefundsHeader } from './RefundsHeader'; import { RefundsTable } from './RefundsTable'; import { SectionIntroduction } from '@app/admin/components/SectionIntroduction'; @@ -58,7 +58,7 @@ async function updateRefundConfiguration(eventId: number, formData: unknown) { .where(tEvents.eventId.equals(eventId)) .executeUpdate(); - await Log({ + RecordLog({ type: kLogType.AdminEventPublishInfo, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/admin/events/[event]/settings/EventSettings.tsx b/app/admin/events/[event]/settings/EventSettings.tsx index c67e4339..05be635e 100644 --- a/app/admin/events/[event]/settings/EventSettings.tsx +++ b/app/admin/events/[event]/settings/EventSettings.tsx @@ -11,7 +11,7 @@ import Grid from '@mui/material/Grid2'; import { type EventAvailabilityStatus, kEventAvailabilityStatus } from '@lib/database/Types'; import { EventSettingsForm } from './EventSettingsForm'; import { FormGridSection } from '@app/admin/components/FormGridSection'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeServerAction } from '@lib/serverAction'; import db, { tEvents } from '@lib/database'; @@ -140,7 +140,7 @@ async function updateEventSettings(eventId: number, formData: unknown) { .where(tEvents.eventId.equals(eventId)) .executeUpdate(); - await Log({ + RecordLog({ type: kLogType.AdminUpdateEvent, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/admin/events/[event]/training/TrainingConfiguration.tsx b/app/admin/events/[event]/training/TrainingConfiguration.tsx index 280c33e5..62b01624 100644 --- a/app/admin/events/[event]/training/TrainingConfiguration.tsx +++ b/app/admin/events/[event]/training/TrainingConfiguration.tsx @@ -9,7 +9,7 @@ import Grid from '@mui/material/Grid2'; import { AvailabilityToggle } from '@app/admin/components/AvailabilityToggle'; import { AvailabilityWindow } from '@app/admin/components/AvailabilityWindow'; import { FormGridSection } from '@app/admin/components/FormGridSection'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { TrainingConfigurationTable } from './TrainingConfigurationTable'; import { executeServerAction } from '@lib/serverAction'; import { getEventNameForId } from '@lib/EventLoader'; @@ -54,7 +54,7 @@ async function updateTrainingConfiguration(eventId: number, formData: unknown) { .where(tEvents.eventId.equals(eventId)) .executeUpdate(); - await Log({ + RecordLog({ type: kLogType.AdminEventPublishInfo, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/admin/system/environments/EnvironmentSection.tsx b/app/admin/system/environments/EnvironmentSection.tsx index 737f1dab..d8ff3daa 100644 --- a/app/admin/system/environments/EnvironmentSection.tsx +++ b/app/admin/system/environments/EnvironmentSection.tsx @@ -15,7 +15,7 @@ import Typography from '@mui/material/Typography'; import { ColorFieldElement } from '@app/admin/volunteers/teams/Team'; import { FormGridSection } from '@app/admin/components/FormGridSection'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeServerAction } from '@lib/serverAction'; import db, { tEnvironments } from '@lib/database'; @@ -69,7 +69,7 @@ async function updateEnvironmentSettings(id: number, formData: unknown) { .executeUpdate(); if (!!affectedRows) { - await Log({ + RecordLog({ type: kLogType.AdminUpdateEnvironment, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/admin/volunteers/[id]/VolunteerPermissions.tsx b/app/admin/volunteers/[id]/VolunteerPermissions.tsx index c0439f65..b772d845 100644 --- a/app/admin/volunteers/[id]/VolunteerPermissions.tsx +++ b/app/admin/volunteers/[id]/VolunteerPermissions.tsx @@ -14,7 +14,7 @@ import Typography from '@mui/material/Typography'; import type { AccessDescriptor, AccessOperation } from '@lib/auth/AccessDescriptor'; import { AccessControl, kAnyEvent, kAnyTeam, type AccessControlParams, type AccessResult } from '@lib/auth/AccessControl'; import { FormGridSection } from '@app/admin/components/FormGridSection'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { SectionIntroduction } from '@app/admin/components/SectionIntroduction'; import { VolunteerPermissionsTable, type VolunteerPermissionStatus } from './VolunteerPermissionsTable'; import { executeServerAction } from '@lib/serverAction'; @@ -153,7 +153,7 @@ async function updateVolunteerPermissions(userId: number, formData: unknown) { .executeUpdate(); if (!!affectedRows) { - await Log({ + RecordLog({ type: kLogType.AdminUpdatePermission, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/content/[[...id]]/route.ts b/app/api/admin/content/[[...id]]/route.ts index 9636e663..03a8404c 100644 --- a/app/api/admin/content/[[...id]]/route.ts +++ b/app/api/admin/content/[[...id]]/route.ts @@ -3,7 +3,7 @@ import { z } from 'zod'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { Temporal } from '@lib/Temporal'; import { createDataTableApi, type DataTableEndpoints } from '../../../createDataTableApi'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; @@ -352,7 +352,7 @@ export const { DELETE, POST, PUT, GET } = createDataTableApi(kContentRowModel, k .executeSelectNoneOrOne(); if (contentContext?.contentType === kContentType.FAQ) { - await Log({ + RecordLog({ type: kLogType.AdminKnowledgeBaseMutation, severity: kLogSeverity.Warning, sourceUser: props.user, @@ -377,7 +377,7 @@ export const { DELETE, POST, PUT, GET } = createDataTableApi(kContentRowModel, k } } - await Log({ + RecordLog({ type: kLogType.AdminContentMutation, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/content/categories/[[...id]]/route.ts b/app/api/admin/content/categories/[[...id]]/route.ts index 3a75bba9..a7a217cf 100644 --- a/app/api/admin/content/categories/[[...id]]/route.ts +++ b/app/api/admin/content/categories/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '../../../../createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getEventBySlug } from '@lib/EventLoader'; import db, { tContentCategories, tContent } from '@lib/database'; @@ -228,7 +228,7 @@ createDataTableApi(kContentCategoryRowModel, kContentCategoryContext, { .selectOneColumn(tContentCategories.categoryTitle) .executeSelectNoneOrOne(); - await Log({ + RecordLog({ type: kLogType.AdminKnowledgeBaseCategoryMutation, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/createEvent.ts b/app/api/admin/createEvent.ts index 852c5974..8d50d78f 100644 --- a/app/api/admin/createEvent.ts +++ b/app/api/admin/createEvent.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; import type { ActionProps } from '../Action'; import { kTemporalZonedDateTime, type ApiDefinition, type ApiRequest, type ApiResponse } from '../Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getEventBySlug } from '@lib/EventLoader'; import db, { tEvents } from '@lib/database'; @@ -95,7 +95,7 @@ export async function createEvent(request: Request, props: ActionProps): Promise .executeInsert(); if (!!insertId) { - Log({ + RecordLog({ type: kLogType.AdminEventCreate, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/displays/[[...id]]/route.ts b/app/api/admin/displays/[[...id]]/route.ts index 103c0b26..19d5301f 100644 --- a/app/api/admin/displays/[[...id]]/route.ts +++ b/app/api/admin/displays/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '../../../createDataTableApi'; import { type DisplayHelpRequestStatus, kDisplayHelpRequestStatus } from '@lib/database/Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { Temporal } from '@lib/Temporal'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { readSetting } from '@lib/Settings'; @@ -177,7 +177,7 @@ export const { GET, DELETE, PUT } = createDataTableApi(kDisplaysRowModel, kDispl }) .executeSelectNoneOrOne(); - await Log({ + RecordLog({ type: kLogType.AdminDisplayMutation, severity: kLogSeverity.Info, sourceUser: props.user, diff --git a/app/api/admin/event/deadlines/[[...id]]/route.ts b/app/api/admin/event/deadlines/[[...id]]/route.ts index 18fc0820..5d6756cd 100644 --- a/app/api/admin/event/deadlines/[[...id]]/route.ts +++ b/app/api/admin/event/deadlines/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '../../../../createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { Temporal } from '@lib/Temporal'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getEventBySlug } from '@lib/EventLoader'; @@ -202,7 +202,7 @@ createDataTableApi(kEventDeadlineRowModel, kEventDeadlineContext, { async writeLog({ context }, mutation, props) { const event = await getEventBySlug(context.event); - await Log({ + RecordLog({ type: kLogType.AdminEventDeadlineMutation, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/event/shifts/[[...id]]/route.ts b/app/api/admin/event/shifts/[[...id]]/route.ts index b2404b86..d40c223e 100644 --- a/app/api/admin/event/shifts/[[...id]]/route.ts +++ b/app/api/admin/event/shifts/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '../../../../createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck, type PermissionAccessCheck } from '@lib/auth/AuthenticationContext'; import { getShiftsForEvent } from '@app/admin/lib/getShiftsForEvent'; import { validateContext } from '../../validateContext'; @@ -398,7 +398,7 @@ createDataTableApi(kEventShiftRowModel, kEventShiftContext, { .selectOneColumn(tShifts.shiftName) .executeSelectNoneOrOne(); - await Log({ + RecordLog({ type: kLogType.AdminEventShiftMutation, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/event/shifts/categories/[[...id]]/route.ts b/app/api/admin/event/shifts/categories/[[...id]]/route.ts index ac0cc71f..87ada069 100644 --- a/app/api/admin/event/shifts/categories/[[...id]]/route.ts +++ b/app/api/admin/event/shifts/categories/[[...id]]/route.ts @@ -4,7 +4,7 @@ import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '../../../../../createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import db, { tShiftsCategories } from '@lib/database'; @@ -179,7 +179,7 @@ createDataTableApi(kEventShiftCategoryRowModel, kEventShiftCategoryContext, { .selectOneColumn(tShiftsCategories.shiftCategoryName) .executeSelectNoneOrOne(); - await Log({ + RecordLog({ type: kLogType.AdminEventShiftCategoryMutation, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/event/teams/[[...id]]/route.ts b/app/api/admin/event/teams/[[...id]]/route.ts index d36aabf2..9c00d763 100644 --- a/app/api/admin/event/teams/[[...id]]/route.ts +++ b/app/api/admin/event/teams/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '../../../../createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getEventBySlug } from '@lib/EventLoader'; import db, { tContent, tEventsTeams, tTeams } from '@lib/database'; @@ -190,7 +190,7 @@ export const { GET, PUT } = createDataTableApi(kEventTeamRowModel, kEventTeamCon .selectOneColumn(tTeams.teamName) .executeSelectNoneOrOne(); - await Log({ + RecordLog({ type: kLogType.AdminUpdateEvent, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/exports/[[...id]]/route.ts b/app/api/admin/exports/[[...id]]/route.ts index 277aa39f..22058279 100644 --- a/app/api/admin/exports/[[...id]]/route.ts +++ b/app/api/admin/exports/[[...id]]/route.ts @@ -7,7 +7,7 @@ import { z } from 'zod'; import type { Event } from '@lib/Event'; import { type DataTableEndpoints, createDataTableApi } from '../../../createDataTableApi'; import { type ExportType, kExportType } from '@lib/database/Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { Temporal } from '@lib/Temporal'; import { executeAccessCheck, type AuthenticationContext } from '@lib/auth/AuthenticationContext'; import { getEventBySlug } from '@lib/EventLoader'; @@ -250,7 +250,7 @@ export const { DELETE, GET, POST } = createDataTableApi(kExportRowModel, kExport }) .executeSelectOne(); - await Log({ + RecordLog({ type: kLogType.AdminExportMutation, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/hotels/[[...id]]/route.ts b/app/api/admin/hotels/[[...id]]/route.ts index ef5f609f..8c551200 100644 --- a/app/api/admin/hotels/[[...id]]/route.ts +++ b/app/api/admin/hotels/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '@app/api/createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getEventBySlug } from '@lib/EventLoader'; import db, { tHotels } from '@lib/database'; @@ -185,7 +185,7 @@ createDataTableApi(kHotelRowModel, kHotelContext, { async writeLog({ context }, mutation, props) { const event = await getEventBySlug(context.event); - await Log({ + RecordLog({ type: kLogType.AdminEventHotelMutation, severity: kLogSeverity.Info, sourceUser: props.user, diff --git a/app/api/admin/hotels/assignments/[[...id]]/route.ts b/app/api/admin/hotels/assignments/[[...id]]/route.ts index 0c9539eb..5fd95d5b 100644 --- a/app/api/admin/hotels/assignments/[[...id]]/route.ts +++ b/app/api/admin/hotels/assignments/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '@app/api/createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { Temporal } from '@lib/Temporal'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getEventBySlug } from '@lib/EventLoader'; @@ -223,7 +223,7 @@ createDataTableApi(kHotelAssignmentRowModel, kHotelAssignmentContext, { if (!!affectedRows) { for (const uid of [ booking.firstUserId, booking.secondUserId, booking.thirdUserId ]) { if (!!uid) { - await Log({ + RecordLog({ type: kLogType.AdminHotelAssignVolunteerDelete, severity: kLogSeverity.Warning, sourceUser: props.user, @@ -318,7 +318,7 @@ createDataTableApi(kHotelAssignmentRowModel, kHotelAssignmentContext, { if (updatedAssignmentSet.has(assignment)) continue; // the volunteer still has an assignment - await Log({ + RecordLog({ type: kLogType.AdminHotelAssignVolunteerDelete, severity: kLogSeverity.Warning, sourceUser: props.user, @@ -335,7 +335,7 @@ createDataTableApi(kHotelAssignmentRowModel, kHotelAssignmentContext, { if (existingAssignmentSet.has(assignment)) continue; // the volunteer already had an assignment - await Log({ + RecordLog({ type: kLogType.AdminHotelAssignVolunteer, severity: kLogSeverity.Warning, sourceUser: props.user, @@ -352,7 +352,7 @@ createDataTableApi(kHotelAssignmentRowModel, kHotelAssignmentContext, { async writeLog({ context }, mutation, props) { const event = await getEventBySlug(context.event); - await Log({ + RecordLog({ type: kLogType.AdminHotelBookingMutation, severity: kLogSeverity.Info, sourceUser: props.user, diff --git a/app/api/admin/program/activities/[[...id]]/route.ts b/app/api/admin/program/activities/[[...id]]/route.ts index b3add0dd..f0120f1f 100644 --- a/app/api/admin/program/activities/[[...id]]/route.ts +++ b/app/api/admin/program/activities/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '../../../../createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getAnPlanActivityUrl } from '@lib/AnPlan'; import { getEventBySlug } from '@lib/EventLoader'; @@ -360,7 +360,7 @@ createDataTableApi(kProgramActivityRowModel, kProgramActivityContext, { .selectOneColumn(tActivities.activityTitle) .executeSelectNoneOrOne(); - await Log({ + RecordLog({ type: kLogType.AdminProgramMutation, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/program/areas/[[...id]]/route.ts b/app/api/admin/program/areas/[[...id]]/route.ts index b92bd200..919b14aa 100644 --- a/app/api/admin/program/areas/[[...id]]/route.ts +++ b/app/api/admin/program/areas/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '../../../../createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getAnPlanAreaUrl } from '@lib/AnPlan'; import { getEventBySlug } from '@lib/EventLoader'; @@ -250,7 +250,7 @@ createDataTableApi(kProgramAreaRowModel, kProgramAreaContext, { tActivitiesAreas.areaName)) .executeSelectNoneOrOne(); - await Log({ + RecordLog({ type: kLogType.AdminProgramMutation, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/program/locations/[[...id]]/route.ts b/app/api/admin/program/locations/[[...id]]/route.ts index 88a588ff..044b8276 100644 --- a/app/api/admin/program/locations/[[...id]]/route.ts +++ b/app/api/admin/program/locations/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '../../../../createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getAnPlanLocationUrl } from '@lib/AnPlan'; import { getEventBySlug } from '@lib/EventLoader'; @@ -269,7 +269,7 @@ createDataTableApi(kProgramLocationRowModel, kProgramLocationContext, { tActivitiesLocations.locationName)) .executeSelectNoneOrOne(); - await Log({ + RecordLog({ type: kLogType.AdminProgramMutation, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/program/requests/[[...id]]/route.ts b/app/api/admin/program/requests/[[...id]]/route.ts index a2c50204..a47a7e8f 100644 --- a/app/api/admin/program/requests/[[...id]]/route.ts +++ b/app/api/admin/program/requests/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { forbidden, notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '@app/api/createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getEventBySlug } from '@lib/EventLoader'; import db, { tActivities, tEventsTeams, tShifts, tUsers } from '@lib/database'; @@ -240,7 +240,7 @@ export const { GET, PUT } = createDataTableApi(kProgramRequestRowModel, kProgram .and(tActivities.activityDeleted.isNull()) .executeSelectNoneOrOne(); - await Log({ + RecordLog({ type: kLogType.AdminEventProgramRequestUpdate, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/refunds/[[...id]]/route.ts b/app/api/admin/refunds/[[...id]]/route.ts index 799db9cd..ee98d092 100644 --- a/app/api/admin/refunds/[[...id]]/route.ts +++ b/app/api/admin/refunds/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '../../../createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getEventBySlug } from '@lib/EventLoader'; import db, { tRefunds, tTeams, tUsers, tUsersEvents } from '@lib/database'; @@ -161,7 +161,7 @@ export const { PUT, GET } = createDataTableApi(kRefundRequestRowModel, kRefundRe async writeLog({ context, id }, mutation, props) { const event = await getEventBySlug(context.event); - await Log({ + RecordLog({ type: kLogType.AdminRefundMutation, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/resetAccessCode.ts b/app/api/admin/resetAccessCode.ts index 0182b181..f0a0ab6f 100644 --- a/app/api/admin/resetAccessCode.ts +++ b/app/api/admin/resetAccessCode.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; import type { ActionProps } from '../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import db, { tUsersAuth } from '@lib/database'; @@ -44,7 +44,7 @@ export async function resetAccessCode(request: Request, props: ActionProps): Pro permission: 'volunteer.account', }); - await Log({ + RecordLog({ type: kLogType.AdminResetAccessCode, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/resetPasswordLink.ts b/app/api/admin/resetPasswordLink.ts index 46ecb2a4..e309fa98 100644 --- a/app/api/admin/resetPasswordLink.ts +++ b/app/api/admin/resetPasswordLink.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; import type { ActionProps } from '../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { sealPasswordResetRequest } from '@lib/auth/PasswordReset'; import db, { tUsers } from '@lib/database'; @@ -57,7 +57,7 @@ export async function resetPasswordLink(request: Request, props: ActionProps): P token: user.sessionToken }); - await Log({ + RecordLog({ type: kLogType.AdminResetPasswordLink, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/retention/[[...id]]/route.ts b/app/api/admin/retention/[[...id]]/route.ts index 57455ca3..8584c0a0 100644 --- a/app/api/admin/retention/[[...id]]/route.ts +++ b/app/api/admin/retention/[[...id]]/route.ts @@ -6,7 +6,7 @@ import { forbidden, notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '@app/api/createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { executeAction } from '@app/api/Action'; import { getEventBySlug } from '@lib/EventLoader'; @@ -342,7 +342,7 @@ export const { GET, PUT } = createDataTableApi(kRetentionRowModel, kRetentionCon if (!event || mutation !== 'Updated') return; - await Log({ + RecordLog({ type: kLogType.AdminEventRetentionUpdate, severity: kLogSeverity.Info, sourceUser: props.user, diff --git a/app/api/admin/retention/remindParticipation.ts b/app/api/admin/retention/remindParticipation.ts index 3e5787de..ab2621d7 100644 --- a/app/api/admin/retention/remindParticipation.ts +++ b/app/api/admin/retention/remindParticipation.ts @@ -6,7 +6,7 @@ import { z } from 'zod'; import type { ActionProps } from '../../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../../Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { SendEmailTask } from '@lib/scheduler/tasks/SendEmailTask'; import { Temporal, formatDate } from '@lib/Temporal'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; @@ -209,7 +209,7 @@ export async function remindParticipation(request: Request, props: ActionProps): phoneNumber = volunteer.phoneNumber; } - await Log({ + RecordLog({ type: kLogType.AdminEventRetentionMessage, severity: kLogSeverity.Info, sourceUser: props.user, diff --git a/app/api/admin/subscriptions/[[...id]]/route.ts b/app/api/admin/subscriptions/[[...id]]/route.ts index fb4f58e4..e476d8dc 100644 --- a/app/api/admin/subscriptions/[[...id]]/route.ts +++ b/app/api/admin/subscriptions/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '../../../createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { queryUsersWithPermission } from '@lib/auth/AccessQuery'; import db, { tSubscriptions, tTeams, tUsers } from '@lib/database'; @@ -248,7 +248,7 @@ createDataTableApi(kSubscriptionRowModel, kSubscriptionContext, { const targetUser = Math.floor(id / 10_000); - await Log({ + RecordLog({ type: kLogType.AdminSubscriptionUpdate, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/trainings/[[...id]]/route.ts b/app/api/admin/trainings/[[...id]]/route.ts index 559a4816..876a02dd 100644 --- a/app/api/admin/trainings/[[...id]]/route.ts +++ b/app/api/admin/trainings/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '@app/api/createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { Temporal } from '@lib/Temporal'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getEventBySlug } from '@lib/EventLoader'; @@ -177,7 +177,7 @@ export const { DELETE, POST, PUT, GET } = createDataTableApi(kTrainingRowModel, async writeLog({ context }, mutation, props) { const event = await getEventBySlug(context.event); - await Log({ + RecordLog({ type: kLogType.AdminEventTrainingMutation, severity: kLogSeverity.Info, sourceUser: props.user, diff --git a/app/api/admin/trainings/assignments/[[...id]]/route.ts b/app/api/admin/trainings/assignments/[[...id]]/route.ts index 59705f74..de24a470 100644 --- a/app/api/admin/trainings/assignments/[[...id]]/route.ts +++ b/app/api/admin/trainings/assignments/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '@app/api/createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getEventBySlug } from '@lib/EventLoader'; import db, { tRoles, tTeams, tTrainingsAssignments, tTrainingsExtra, tUsersEvents, tUsers } @@ -322,7 +322,7 @@ createDataTableApi(kTrainingAssignmentRowModel, kTrainingAssignmentContext, { .selectOneColumn(tTrainingsAssignments.assignmentUserId) .executeSelectNoneOrOne(); - await Log({ + RecordLog({ type: kLogType.AdminEventTrainingAssignment, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/trainings/extra/[[...id]]/route.ts b/app/api/admin/trainings/extra/[[...id]]/route.ts index 7012abec..21f42f1b 100644 --- a/app/api/admin/trainings/extra/[[...id]]/route.ts +++ b/app/api/admin/trainings/extra/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '@app/api/createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { Temporal } from '@lib/Temporal'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getEventBySlug } from '@lib/EventLoader'; @@ -211,7 +211,7 @@ createDataTableApi(kTrainingExtraRowModel, kTrainingExtraContext, { if (!event) return; - await Log({ + RecordLog({ type: kLogType.AdminEventTrainingExtraMutation, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/updateActivation.ts b/app/api/admin/updateActivation.ts index e46d0516..97beff12 100644 --- a/app/api/admin/updateActivation.ts +++ b/app/api/admin/updateActivation.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; import type { ActionProps } from '../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; -import { Log, kLogType } from '@lib/Log'; +import { RecordLog, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import db, { tUsers } from '@lib/database'; @@ -54,7 +54,7 @@ export async function updateActivation(request: Request, props: ActionProps): Pr .executeUpdate(/* min= */ 0, /* max= */ 1); if (!!affectedRows) { - await Log({ + RecordLog({ type: kLogType.AdminUpdateActivation, sourceUser: props.user, targetUser: request.userId, diff --git a/app/api/admin/updateEvent.ts b/app/api/admin/updateEvent.ts index 29cbc300..54fdc1f3 100644 --- a/app/api/admin/updateEvent.ts +++ b/app/api/admin/updateEvent.ts @@ -6,7 +6,7 @@ import { z } from 'zod'; import type { ActionProps } from '../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getEventBySlug } from '@lib/EventLoader'; import { storeBlobData } from '@lib/database/BlobStore'; @@ -86,7 +86,7 @@ export async function updateEvent(request: Request, props: ActionProps): Promise .executeUpdate(/* min= */ 0, /* max= */ 1); if (affectedRows > 0) { - await Log({ + RecordLog({ type: kLogType.AdminUpdateEvent, severity: kLogSeverity.Warning, sourceUser: props.user, @@ -114,7 +114,7 @@ export async function updateEvent(request: Request, props: ActionProps): Promise .executeUpdate(/* min= */ 0, /* max= */ 1); if (!!affectedRows) { - await Log({ + RecordLog({ type: kLogType.AdminUpdateEvent, severity: kLogSeverity.Info, sourceUser: props.user, @@ -144,7 +144,7 @@ export async function updateEvent(request: Request, props: ActionProps): Promise .executeUpdate(/* min= */ 0, /* max= */ 1); if (affectedRows > 0) { - await Log({ + RecordLog({ type: kLogType.AdminUpdateEvent, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/updateIntegration.ts b/app/api/admin/updateIntegration.ts index 3133ca7d..d318e006 100644 --- a/app/api/admin/updateIntegration.ts +++ b/app/api/admin/updateIntegration.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; import type { ActionProps } from '../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { writeSettings } from '@lib/Settings'; @@ -102,7 +102,7 @@ export async function updateIntegration(request: Request, props: ActionProps): P 'integration-animecon-scopes': request.animecon.scopes, }); - await Log({ + RecordLog({ type: kLogType.AdminUpdateIntegration, severity: kLogSeverity.Warning, sourceUser: props.user, @@ -120,7 +120,7 @@ export async function updateIntegration(request: Request, props: ActionProps): P 'integration-email-smtp-password': request.email.password, }); - await Log({ + RecordLog({ type: kLogType.AdminUpdateIntegration, severity: kLogSeverity.Warning, sourceUser: props.user, @@ -138,7 +138,7 @@ export async function updateIntegration(request: Request, props: ActionProps): P 'integration-google-project-id': request.google.projectId, }); - await Log({ + RecordLog({ type: kLogType.AdminUpdateIntegration, severity: kLogSeverity.Warning, sourceUser: props.user, @@ -157,7 +157,7 @@ export async function updateIntegration(request: Request, props: ActionProps): P 'integration-twilio-region': request.twilio.region, }); - await Log({ + RecordLog({ type: kLogType.AdminUpdateIntegration, severity: kLogSeverity.Warning, sourceUser: props.user, @@ -176,7 +176,7 @@ export async function updateIntegration(request: Request, props: ActionProps): P 'integration-vertex-top-p': request.vertexAi.topP, }); - await Log({ + RecordLog({ type: kLogType.AdminUpdateIntegration, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/updateSettings.ts b/app/api/admin/updateSettings.ts index 3e73292d..b03f0d48 100644 --- a/app/api/admin/updateSettings.ts +++ b/app/api/admin/updateSettings.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; import type { ActionProps } from '../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { writeSettings } from '@lib/Settings'; @@ -68,7 +68,7 @@ export async function updateSettings(request: Request, props: ActionProps): Prom } await writeSettings(settings as any); - await Log({ + RecordLog({ type: kLogType.AdminUpdateSettings, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/updateTeam.ts b/app/api/admin/updateTeam.ts index ee283432..84f3c08a 100644 --- a/app/api/admin/updateTeam.ts +++ b/app/api/admin/updateTeam.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; import type { ActionProps } from '../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { clearEnvironmentCache } from '@lib/Environment'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import db, { tTeams, tTeamsRoles } from '@lib/database'; @@ -108,7 +108,7 @@ export async function updateTeam(request: Request, props: ActionProps): Promise< .executeInsert(); }); - await Log({ + RecordLog({ type: kLogType.AdminUpdateTeam, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/updateVolunteer.ts b/app/api/admin/updateVolunteer.ts index 77ca5fd3..0405b79f 100644 --- a/app/api/admin/updateVolunteer.ts +++ b/app/api/admin/updateVolunteer.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; import type { ActionProps } from '../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { Temporal } from '@lib/Temporal'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { isUsernameAvailable } from '@lib/auth/Authentication'; @@ -102,7 +102,7 @@ export async function updateVolunteer(request: Request, props: ActionProps): Pro if (!affectedRows) return { success: false, error: 'Unable to update the existing user information' }; - await Log({ + RecordLog({ type: kLogType.AdminUpdateVolunteer, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/vendors/[[...id]]/route.ts b/app/api/admin/vendors/[[...id]]/route.ts index 85db841e..1eff4811 100644 --- a/app/api/admin/vendors/[[...id]]/route.ts +++ b/app/api/admin/vendors/[[...id]]/route.ts @@ -5,7 +5,7 @@ import { notFound } from 'next/navigation'; import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '@app/api/createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getEventBySlug } from '@lib/EventLoader'; import { readSetting } from '@lib/Settings'; @@ -271,7 +271,7 @@ export const { DELETE, POST, PUT, GET } = createDataTableApi(kVendorRowModel, kV [kVendorTeam.Security]: 'Security', }; - await Log({ + RecordLog({ type: kLogType.AdminVendorMutation, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/vendors/updateVendorSchedule.ts b/app/api/admin/vendors/updateVendorSchedule.ts index 4206ec33..38c73c7e 100644 --- a/app/api/admin/vendors/updateVendorSchedule.ts +++ b/app/api/admin/vendors/updateVendorSchedule.ts @@ -7,7 +7,7 @@ import { z } from 'zod'; import type { ActionProps } from '../../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../../Types'; import { type VendorTeam, kVendorTeam } from '@lib/database/Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { getEventBySlug } from '@lib/EventLoader'; import db, { tVendors, tVendorsSchedule } from '@lib/database'; @@ -181,7 +181,7 @@ export async function updateVendorSchedule(request: Request, props: ActionProps) [kVendorTeam.Security]: 'Security', }; - await Log({ + RecordLog({ type: kLogType.AdminVendorScheduleUpdate, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/volunteerContactInfo.ts b/app/api/admin/volunteerContactInfo.ts index 2eb4be9b..1b24e0eb 100644 --- a/app/api/admin/volunteerContactInfo.ts +++ b/app/api/admin/volunteerContactInfo.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; import type { ActionProps } from '../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import db, { tUsers, tUsersEvents, tEvents } from '@lib/database'; @@ -75,7 +75,7 @@ export async function volunteerContactInfo(request: Request, props: ActionProps) .executeSelectNoneOrOne(); if (contactInformation) { - await Log({ + RecordLog({ type: kLogType.AdminAccessVolunteerInfo, severity: kLogSeverity.Info, sourceUser: props.user, diff --git a/app/api/admin/volunteerRoles.tsx b/app/api/admin/volunteerRoles.tsx index 54cefa39..9431df75 100644 --- a/app/api/admin/volunteerRoles.tsx +++ b/app/api/admin/volunteerRoles.tsx @@ -5,7 +5,7 @@ import { z } from 'zod'; import type { ActionProps } from '../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import db, { tRoles, tTeamsRoles, tUsersEvents } from '@lib/database'; @@ -125,7 +125,7 @@ export async function volunteerRoles(request: Request, props: ActionProps): Prom .executeUpdate(/* min= */ 0, /* max= */ 1); if (affectedRows > 0) { - await Log({ + RecordLog({ type: kLogType.AdminEventRoleUpdate, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/volunteerTeams.ts b/app/api/admin/volunteerTeams.ts index f45af51f..f04c5e69 100644 --- a/app/api/admin/volunteerTeams.ts +++ b/app/api/admin/volunteerTeams.ts @@ -6,7 +6,7 @@ import { z } from 'zod'; import type { ActionProps } from '../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { SendEmailTask } from '@lib/scheduler/tasks/SendEmailTask'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { getEventBySlug } from '@lib/EventLoader'; @@ -215,7 +215,7 @@ export async function volunteerTeams(request: Request, props: ActionProps): Prom } if (affectedRows > 0) { - await Log({ + RecordLog({ type: kLogType.AdminEventTeamUpdate, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/admin/volunteers/roles/[[...id]]/route.ts b/app/api/admin/volunteers/roles/[[...id]]/route.ts index cf25d763..c6f01d77 100644 --- a/app/api/admin/volunteers/roles/[[...id]]/route.ts +++ b/app/api/admin/volunteers/roles/[[...id]]/route.ts @@ -4,7 +4,7 @@ import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '../../../../createDataTableApi'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import db, { tRoles } from '@lib/database'; @@ -156,7 +156,7 @@ export const { GET, PUT } = createDataTableApi(kRoleRowModel, kRoleContext, { .selectOneColumn(tRoles.roleName) .executeSelectNoneOrOne(); - await Log({ + RecordLog({ type: kLogType.AdminUpdateRole, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/ai/updateSettings.ts b/app/api/ai/updateSettings.ts index e8595f35..e368be80 100644 --- a/app/api/ai/updateSettings.ts +++ b/app/api/ai/updateSettings.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; import type { ActionProps } from '../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import { writeSettings } from '@lib/Settings'; @@ -64,7 +64,7 @@ export async function updateSettings(request: Request, props: ActionProps): Prom 'gen-ai-system-instruction': request.systemInstruction, }); - await Log({ + RecordLog({ type: kLogType.AdminUpdateAiSetting, severity: kLogSeverity.Warning, sourceUser: props.user, @@ -90,7 +90,7 @@ export async function updateSettings(request: Request, props: ActionProps): Prom request.prompts['gen-ai-intention-remind-participation'], }); - await Log({ + RecordLog({ type: kLogType.AdminUpdateAiSetting, severity: kLogSeverity.Warning, sourceUser: props.user, diff --git a/app/api/application/updateApplication.ts b/app/api/application/updateApplication.ts index ee37c739..9ef644b6 100644 --- a/app/api/application/updateApplication.ts +++ b/app/api/application/updateApplication.ts @@ -5,7 +5,7 @@ import { forbidden, notFound } from 'next/navigation'; import { z } from 'zod'; import type { ActionProps } from '../Action'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { SendEmailTask } from '@lib/scheduler/tasks/SendEmailTask'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import db, { tEvents, tEventsTeams, tTeams, tUsersEvents, tUsers } from '@lib/database'; @@ -224,7 +224,7 @@ export async function updateApplication(request: Request, props: ActionProps): P skipLog = true; - await Log({ + RecordLog({ type: kLogType.EventVolunteerNotes, severity: kLogSeverity.Info, sourceUser: props.user, @@ -310,7 +310,7 @@ export async function updateApplication(request: Request, props: ActionProps): P .and(tUsersEvents.teamId.equals(teamId)) .executeUpdate(/* min= */ 0, /* max= */ 1); - await Log({ + RecordLog({ type: kLogType.AdminUpdateTeamVolunteerStatus, severity: kLogSeverity.Warning, sourceUser: props.user, @@ -328,7 +328,7 @@ export async function updateApplication(request: Request, props: ActionProps): P // --------------------------------------------------------------------------------------------- if (!!affectedRows && !skipLog) { - await Log({ + RecordLog({ type: kLogType.AdminUpdateTeamVolunteer, severity: kLogSeverity.Info, sourceUser: props.user, diff --git a/app/api/auth/confirmIdentity.ts b/app/api/auth/confirmIdentity.ts index 3153062b..104a37f3 100644 --- a/app/api/auth/confirmIdentity.ts +++ b/app/api/auth/confirmIdentity.ts @@ -7,7 +7,7 @@ import { z } from 'zod'; import type { ActionProps } from '../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { determineRpID, retrieveCredentials, storeUserChallenge } from './passkeys/PasskeyUtils'; import { isValidActivatedUser } from '@lib/auth/Authentication'; @@ -53,7 +53,7 @@ type Response = ApiResponse; export async function confirmIdentity(request: Request, props: ActionProps): Promise { const user = await isValidActivatedUser(request.username); - await Log({ + RecordLog({ type: kLogType.AccountIdentityCheck, severity: kLogSeverity.Debug, data: { diff --git a/app/api/auth/passkeys/deletePasskey.ts b/app/api/auth/passkeys/deletePasskey.ts index ee314eaa..d1bbbc7f 100644 --- a/app/api/auth/passkeys/deletePasskey.ts +++ b/app/api/auth/passkeys/deletePasskey.ts @@ -6,7 +6,7 @@ import { z } from 'zod'; import type { ActionProps } from '../../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../../Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { deleteCredential } from './PasskeyUtils'; /** @@ -46,7 +46,7 @@ export async function deletePasskey(request: Request, props: ActionProps): Promi const credentialDeleted = await deleteCredential(props.user, request.id); if (credentialDeleted) { - await Log({ + RecordLog({ type: kLogType.AccountPasskeyCreate, severity: kLogSeverity.Debug, sourceUser: props.user, diff --git a/app/api/auth/passkeys/registerPasskey.ts b/app/api/auth/passkeys/registerPasskey.ts index 3f3208ab..fb59f169 100644 --- a/app/api/auth/passkeys/registerPasskey.ts +++ b/app/api/auth/passkeys/registerPasskey.ts @@ -7,7 +7,7 @@ import { z } from 'zod'; import type { ActionProps } from '../../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../../Types'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLog, kLogSeverity, kLogType } from '@lib/Log'; import { determineRpID, retrieveUserChallenge, storePasskeyRegistration, storeUserChallenge } from './PasskeyUtils'; @@ -98,7 +98,7 @@ export async function registerPasskey(request: Request, props: ActionProps): Pro await storeUserChallenge(props.user, /* reset= */ null); - await Log({ + RecordLog({ type: kLogType.AccountPasskeyCreate, severity: kLogSeverity.Debug, sourceUser: props.user, diff --git a/app/api/auth/passwordChange.ts b/app/api/auth/passwordChange.ts index 197c43ee..9a553040 100644 --- a/app/api/auth/passwordChange.ts +++ b/app/api/auth/passwordChange.ts @@ -6,7 +6,7 @@ import { z } from 'zod'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; import type { ActionProps } from '../Action'; -import { Log, kLogType } from '@lib/Log'; +import { RecordLog, kLogType } from '@lib/Log'; import { authenticateUser } from '@lib/auth/Authentication'; import { updateUserPassword } from './passwordReset'; @@ -61,7 +61,7 @@ export async function passwordChange(request: Request, props: ActionProps): Prom return { success: false, error: 'That is not your current password…' }; await updateUserPassword(props.user.userId, request.newPassword, /* incrementSession= */ false); - await Log({ + RecordLog({ type: kLogType.AccountPasswordUpdate, sourceUser: props.user, data: { ip: props.ip }, diff --git a/app/api/auth/passwordReset.ts b/app/api/auth/passwordReset.ts index e5452a2d..720f53d6 100644 --- a/app/api/auth/passwordReset.ts +++ b/app/api/auth/passwordReset.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; import type { ActionProps } from '../Action'; -import { Log, kLogType } from '@lib/Log'; +import { RecordLog, kLogType } from '@lib/Log'; import { PlaywrightHooks } from '@lib/PlaywrightHooks'; import { authenticateUser, getUserSessionToken } from '@lib/auth/Authentication'; @@ -109,7 +109,7 @@ export async function passwordReset(request: Request, props: ActionProps): Promi await writeSealedSessionCookie( { id: user.userId, token: sessionToken }, props.responseHeaders); - await Log({ + RecordLog({ type: kLogType.AccountPasswordReset, sourceUser: user, data: { ip: props.ip }, diff --git a/app/api/auth/passwordResetRequest.ts b/app/api/auth/passwordResetRequest.ts index d3d1ff37..1e36c309 100644 --- a/app/api/auth/passwordResetRequest.ts +++ b/app/api/auth/passwordResetRequest.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; import type { ActionProps } from '../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; -import { Log, kLogType } from '@lib/Log'; +import { RecordLog, kLogType } from '@lib/Log'; import { SendEmailTask } from '@lib/scheduler/tasks/SendEmailTask'; import { getStaticContent } from '@lib/Content'; import { sealPasswordResetRequest } from '@lib/auth/PasswordReset'; @@ -80,7 +80,7 @@ export async function passwordResetRequest(request: Request, props: ActionProps) }, }); - await Log({ + RecordLog({ type: kLogType.AccountPasswordResetRequest, sourceUser: passwordResetData.userId, data: { ip: props.ip } diff --git a/app/api/auth/register.ts b/app/api/auth/register.ts index cafe291f..1dfaccd7 100644 --- a/app/api/auth/register.ts +++ b/app/api/auth/register.ts @@ -5,8 +5,8 @@ import { z } from 'zod'; import type { ActionProps } from '../Action'; import type { ApiDefinition, ApiRequest, ApiResponse } from '../Types'; -import { Log, kLogType } from '@lib/Log'; import { Publish, kSubscriptionType } from '@lib/subscriptions'; +import { RecordLog, kLogType } from '@lib/Log'; import { SendEmailTask } from '@lib/scheduler/tasks/SendEmailTask'; import { createAccount, isUsernameAvailable } from '@lib/auth/Authentication'; import { getStaticContent } from '@lib/Content'; @@ -146,7 +146,7 @@ export async function register(request: Request, props: ActionProps): Promise }) .executeInsert(); - await Log({ + RecordLog({ type: kLogType.ExportDataAccess, sourceUser: props.user, data: { diff --git a/app/api/nardo/[[...id]]/route.ts b/app/api/nardo/[[...id]]/route.ts index 060ac177..e468cec8 100644 --- a/app/api/nardo/[[...id]]/route.ts +++ b/app/api/nardo/[[...id]]/route.ts @@ -4,7 +4,7 @@ import { z } from 'zod'; import { type DataTableEndpoints, createDataTableApi } from '../../createDataTableApi'; -import { Log, kLogType } from '@lib/Log'; +import { RecordLog, kLogType } from '@lib/Log'; import { Temporal } from '@lib/Temporal'; import { executeAccessCheck } from '@lib/auth/AuthenticationContext'; import db, { tNardo, tUsers } from '@lib/database'; @@ -154,7 +154,7 @@ export const { DELETE, GET, POST, PUT } = createDataTableApi(kNardoRowModel, kNa }, async writeLog(request, mutation, props) { - await Log({ + RecordLog({ type: kLogType.AdminNardoMutation, sourceUser: props.user!.userId, data: { mutation }, diff --git a/app/lib/Log.ts b/app/lib/Log.ts index 7eaafd10..edd8603e 100644 --- a/app/lib/Log.ts +++ b/app/lib/Log.ts @@ -1,6 +1,9 @@ // Copyright 2023 Peter Beverloo & AnimeCon. All rights reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. +import { after } from 'next/server'; +import { headers } from 'next/headers'; + import type { User } from '@lib/auth/User'; import { PlaywrightHooks } from './PlaywrightHooks'; import db, { tLogs } from '@lib/database'; @@ -138,10 +141,10 @@ export interface LogEntry { } /** - * Logs the given `entry` to the database. Callers to this method must wait for this call to - * complete in order to avoid concurrent queries running on the database. + * Logs the given `entry` to the database. This function will be executed after the current request + * has completed, to avoid blocking the response as users don't get value out of log entries. */ -export async function Log(entry: LogEntry): Promise { +export function RecordLog(entry: LogEntry): void { const { sourceUser, targetUser } = entry; let sourceUserId: number | null = null; @@ -158,11 +161,65 @@ export async function Log(entry: LogEntry): Promise { if (PlaywrightHooks.isActive() && PlaywrightHooks.isPlaywrightUser(sourceUserId, targetUserId)) return; // don't create log entries on behalf of Playwright users + after(async () => { + const requestHeaders = await headers(); + + const logSourceIpAddress = requestHeaders.get('x-forwarded-for'); + const logSourceUserAgent = requestHeaders.get('user-agent'); + + await db.insertInto(tLogs) + .values({ + logType: entry.type, + logSeverity: severity, + logSourceUserId: sourceUserId, + logSourceIpAddress, + logSourceUserAgent, + logTargetUserId: targetUserId, + logData: data, + }).executeInsert(); + }); +} + +/** + * Version of `RecordLog` that will write the given `entry` to the database immediately, in a way + * that can be waited on. Should be used sparsely, generally `RecordLog` should be preferred unless + * the log might be issued outside of a request context. + */ +export async function RecordLogImmediate(entry: LogEntry): Promise { + const { sourceUser, targetUser } = entry; + + let sourceUserId: number | null = null; + if (sourceUser) + sourceUserId = typeof sourceUser === 'number' ? sourceUser : sourceUser.userId; + + let targetUserId: number | null = null; + if (targetUser) + targetUserId = typeof targetUser === 'number' ? targetUser : targetUser.userId; + + const data = entry.data ? JSON.stringify(entry.data) : null; + const severity = entry.severity ?? kLogSeverity.Info; + + if (PlaywrightHooks.isActive() && PlaywrightHooks.isPlaywrightUser(sourceUserId, targetUserId)) + return; // don't create log entries on behalf of Playwright users + + let logSourceIpAddress: string | null = null; + let logSourceUserAgent: string | null = null; + + try { + const requestHeaders = await headers(); + + logSourceIpAddress = requestHeaders.get('x-forwarded-for'); + logSourceUserAgent = requestHeaders.get('user-agent'); + + } catch (error) { /* ignore for non-request contexts */ } + await db.insertInto(tLogs) .values({ logType: entry.type, logSeverity: severity, logSourceUserId: sourceUserId, + logSourceIpAddress, + logSourceUserAgent, logTargetUserId: targetUserId, logData: data, }).executeInsert(); diff --git a/app/lib/database/Connection.ts b/app/lib/database/Connection.ts index ab84ba11..a355cdd2 100644 --- a/app/lib/database/Connection.ts +++ b/app/lib/database/Connection.ts @@ -11,7 +11,7 @@ import { MockQueryRunner, type QueryType as MockQueryType } from 'ts-sql-query/queryRunners/MockQueryRunner'; import type { PlainDate, ZonedDateTime } from '@lib/Temporal'; -import { Log, kLogSeverity, kLogType } from '@lib/Log'; +import { RecordLogImmediate, kLogSeverity, kLogType } from '@lib/Log'; declare module globalThis { let animeConConnectionPool: Pool | undefined; @@ -88,7 +88,7 @@ class ErrorReportingQueryRunner extends InterceptorQueryRunner { if (query.includes('database-error') || params.includes('database-error')) return; // prevent recursion - Log({ + RecordLogImmediate({ type: kLogType.DatabaseError, severity: kLogSeverity.Error, data: { diff --git a/app/lib/database/scheme/LogsTable.ts b/app/lib/database/scheme/LogsTable.ts index b11f0a54..4f3ec039 100644 --- a/app/lib/database/scheme/LogsTable.ts +++ b/app/lib/database/scheme/LogsTable.ts @@ -24,6 +24,8 @@ export class LogsTable extends Table { logType = this.column('log_type', 'string'); logSeverity = this.column('log_severity', 'enum', 'LogSeverity'); logSourceUserId = this.optionalColumnWithDefaultValue('log_source_user_id', 'int'); + logSourceIpAddress = this.optionalColumnWithDefaultValue('log_source_ip_address', 'string'); + logSourceUserAgent = this.optionalColumnWithDefaultValue('log_source_user_agent', 'string'); logTargetUserId = this.optionalColumnWithDefaultValue('log_target_user_id', 'int'); logData = this.optionalColumnWithDefaultValue('log_data', 'string'); logDeleted = this.optionalColumnWithDefaultValue('log_deleted', 'customLocalDateTime', 'dateTime', TemporalTypeAdapter); diff --git a/ts-sql.scheme.yaml b/ts-sql.scheme.yaml index 77dd2168..586fe74f 100644 --- a/ts-sql.scheme.yaml +++ b/ts-sql.scheme.yaml @@ -305,117 +305,6 @@ tables: KEY `event_id` (`event_id`), CONSTRAINT `hotels_event_id` FOREIGN KEY (`event_id`) REFERENCES `events` (`event_id`) ON DELETE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=[Redacted by tbls] DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci -- name: logs - type: BASE TABLE - comment: "" - columns: - - name: log_id - type: int(8) unsigned - nullable: false - default: null - extraDef: auto_increment - comment: "" - - name: log_date - type: timestamp - nullable: false - default: current_timestamp() - comment: "" - - name: log_type - type: varchar(48) - nullable: false - default: null - comment: "" - - name: log_severity - type: enum('Debug','Info','Warning','Error') - nullable: false - default: null - comment: "" - - name: log_source_user_id - type: int(8) unsigned - nullable: true - default: "NULL" - comment: "" - - name: log_target_user_id - type: int(8) unsigned - nullable: true - default: "NULL" - comment: "" - - name: log_data - type: text - nullable: true - default: "NULL" - comment: "" - - name: log_deleted - type: datetime - nullable: true - default: "NULL" - comment: "" - indexes: - - name: log_source_user_id - def: KEY log_source_user_id (log_source_user_id) USING BTREE - table: logs - columns: - - log_source_user_id - comment: "" - - name: log_target_user_id - def: KEY log_target_user_id (log_target_user_id) USING BTREE - table: logs - columns: - - log_target_user_id - comment: "" - - name: PRIMARY - def: PRIMARY KEY (log_id) USING BTREE - table: logs - columns: - - log_id - comment: "" - constraints: - - name: logs_log_source_user_id - type: FOREIGN KEY - def: FOREIGN KEY (log_source_user_id) REFERENCES users (user_id) - table: logs - referencedTable: users - columns: - - log_source_user_id - referencedColumns: - - user_id - comment: "" - - name: logs_log_target_user_id - type: FOREIGN KEY - def: FOREIGN KEY (log_target_user_id) REFERENCES users (user_id) - table: logs - referencedTable: users - columns: - - log_target_user_id - referencedColumns: - - user_id - comment: "" - - name: PRIMARY - type: PRIMARY KEY - def: PRIMARY KEY (log_id) - table: logs - referencedTable: null - columns: - - log_id - referencedColumns: [] - comment: "" - triggers: [] - def: |- - CREATE TABLE `logs` ( - `log_id` int(8) unsigned NOT NULL AUTO_INCREMENT, - `log_date` timestamp NOT NULL DEFAULT current_timestamp(), - `log_type` varchar(48) NOT NULL, - `log_severity` enum('Debug','Info','Warning','Error') NOT NULL, - `log_source_user_id` int(8) unsigned DEFAULT NULL, - `log_target_user_id` int(8) unsigned DEFAULT NULL, - `log_data` text DEFAULT NULL, - `log_deleted` datetime DEFAULT NULL, - PRIMARY KEY (`log_id`), - KEY `log_target_user_id` (`log_target_user_id`), - KEY `log_source_user_id` (`log_source_user_id`), - CONSTRAINT `logs_log_source_user_id` FOREIGN KEY (`log_source_user_id`) REFERENCES `users` (`user_id`), - CONSTRAINT `logs_log_target_user_id` FOREIGN KEY (`log_target_user_id`) REFERENCES `users` (`user_id`) - ) ENGINE=InnoDB AUTO_INCREMENT=[Redacted by tbls] DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci - name: roles type: BASE TABLE comment: "" @@ -4718,6 +4607,129 @@ tables: PRIMARY KEY (`whatsapp_message_id`), KEY `whatsapp_message_recipient_user_id` (`whatsapp_recipient_user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci +- name: logs + type: BASE TABLE + comment: "" + columns: + - name: log_id + type: int(8) unsigned + nullable: false + default: null + extraDef: auto_increment + comment: "" + - name: log_date + type: timestamp + nullable: false + default: current_timestamp() + comment: "" + - name: log_type + type: varchar(48) + nullable: false + default: null + comment: "" + - name: log_severity + type: enum('Debug','Info','Warning','Error') + nullable: false + default: null + comment: "" + - name: log_source_user_id + type: int(8) unsigned + nullable: true + default: "NULL" + comment: "" + - name: log_source_ip_address + type: varchar(45) + nullable: true + default: "NULL" + comment: "" + - name: log_source_user_agent + type: text + nullable: true + default: "NULL" + comment: "" + - name: log_target_user_id + type: int(8) unsigned + nullable: true + default: "NULL" + comment: "" + - name: log_data + type: text + nullable: true + default: "NULL" + comment: "" + - name: log_deleted + type: datetime + nullable: true + default: "NULL" + comment: "" + indexes: + - name: log_source_user_id + def: KEY log_source_user_id (log_source_user_id) USING BTREE + table: logs + columns: + - log_source_user_id + comment: "" + - name: log_target_user_id + def: KEY log_target_user_id (log_target_user_id) USING BTREE + table: logs + columns: + - log_target_user_id + comment: "" + - name: PRIMARY + def: PRIMARY KEY (log_id) USING BTREE + table: logs + columns: + - log_id + comment: "" + constraints: + - name: logs_log_source_user_id + type: FOREIGN KEY + def: FOREIGN KEY (log_source_user_id) REFERENCES users (user_id) + table: logs + referencedTable: users + columns: + - log_source_user_id + referencedColumns: + - user_id + comment: "" + - name: logs_log_target_user_id + type: FOREIGN KEY + def: FOREIGN KEY (log_target_user_id) REFERENCES users (user_id) + table: logs + referencedTable: users + columns: + - log_target_user_id + referencedColumns: + - user_id + comment: "" + - name: PRIMARY + type: PRIMARY KEY + def: PRIMARY KEY (log_id) + table: logs + referencedTable: null + columns: + - log_id + referencedColumns: [] + comment: "" + triggers: [] + def: |- + CREATE TABLE `logs` ( + `log_id` int(8) unsigned NOT NULL AUTO_INCREMENT, + `log_date` timestamp NOT NULL DEFAULT current_timestamp(), + `log_type` varchar(48) NOT NULL, + `log_severity` enum('Debug','Info','Warning','Error') NOT NULL, + `log_source_user_id` int(8) unsigned DEFAULT NULL, + `log_source_ip_address` varchar(45) DEFAULT NULL, + `log_source_user_agent` text DEFAULT NULL, + `log_target_user_id` int(8) unsigned DEFAULT NULL, + `log_data` text DEFAULT NULL, + `log_deleted` datetime DEFAULT NULL, + PRIMARY KEY (`log_id`), + KEY `log_target_user_id` (`log_target_user_id`), + KEY `log_source_user_id` (`log_source_user_id`), + CONSTRAINT `logs_log_source_user_id` FOREIGN KEY (`log_source_user_id`) REFERENCES `users` (`user_id`), + CONSTRAINT `logs_log_target_user_id` FOREIGN KEY (`log_target_user_id`) REFERENCES `users` (`user_id`) + ) ENGINE=InnoDB AUTO_INCREMENT=[Redacted by tbls] DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci - name: schedule type: BASE TABLE comment: "" @@ -5334,26 +5346,6 @@ relations: parentCardinality: Exactly one def: FOREIGN KEY (event_id) REFERENCES events (event_id) virtual: false -- table: logs - columns: - - log_source_user_id - cardinality: Zero or more - parentTable: users - parentColumns: - - user_id - parentCardinality: Zero or one - def: FOREIGN KEY (log_source_user_id) REFERENCES users (user_id) - virtual: false -- table: logs - columns: - - log_target_user_id - cardinality: Zero or more - parentTable: users - parentColumns: - - user_id - parentCardinality: Zero or one - def: FOREIGN KEY (log_target_user_id) REFERENCES users (user_id) - virtual: false - table: storage columns: - user_id @@ -5474,6 +5466,26 @@ relations: parentCardinality: Exactly one def: FOREIGN KEY (team_id) REFERENCES teams (team_id) virtual: false +- table: logs + columns: + - log_source_user_id + cardinality: Zero or more + parentTable: users + parentColumns: + - user_id + parentCardinality: Zero or one + def: FOREIGN KEY (log_source_user_id) REFERENCES users (user_id) + virtual: false +- table: logs + columns: + - log_target_user_id + cardinality: Zero or more + parentTable: users + parentColumns: + - user_id + parentCardinality: Zero or one + def: FOREIGN KEY (log_target_user_id) REFERENCES users (user_id) + virtual: false - table: schedule columns: - event_id