Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | 61x 18006x 61x 2078x 9x 2078x 61x 4489x 61x 23628x 61x 2078x 2078x 2699x 61x 4489x 61x 61x 61x | // Registers the global mongoose plugins, which are applied when a model is
// compiled below, so it has to stay above the other imports
import "server/db/mongoosePlugins";
import mongoose, { ObjectId } from "mongoose";
import mongooseLeanVirtuals from "mongoose-lean-virtuals";
import { z } from "zod";
import { StoredEmailSchema } from "shared/constants/validation";
import { EventLogAction } from "shared/types/models/eventLog";
import { ProgramType } from "shared/types/models/programItem";
import { UserGroup } from "shared/types/models/user";
const LotterySignupSchemaDb = z.object({
programItemId: z.string(),
priority: z.number(),
signedToStartTime: z.date().transform((date) => date.toISOString()),
});
const EventLogItemSchemaDb = z.object({
eventLogItemId: z.custom<ObjectId>().transform(String),
action: z.enum(EventLogAction),
isSeen: z.boolean(),
programItemId: z.string(),
programItemStartTime: z.date().transform((date) => date.toISOString()),
lastProgramItemEndTime: z.optional(
z.date().transform((date) => date.toISOString()),
),
programType: z.optional(z.enum(ProgramType)),
createdAt: z.date().transform((date) => date.toISOString()),
});
export const UserSchemaDb = z
.object({
kompassiId: z.string(),
kompassiUsernameAccepted: z.boolean(),
username: z.string(),
password: z.string(),
userGroup: z.enum(UserGroup),
serial: z.string(),
groupCode: z.string(),
isGroupCreator: z.boolean(),
favoriteProgramItemIds: z.array(z.string()),
lotterySignups: z.array(LotterySignupSchemaDb),
createdAt: z.date().transform((date) => date.toISOString()),
eventLogItems: z.array(EventLogItemSchemaDb),
email: StoredEmailSchema,
emailNotificationPermitAsked: z.boolean(),
})
.strip();
const lotterySignupSchema = new mongoose.Schema({
programItemId: { type: String, required: true },
priority: { type: Number, required: true },
signedToStartTime: {
type: Date,
get: (value: Date) => new Date(value),
required: true,
},
});
const eventLogItemSchema = new mongoose.Schema(
{
action: { type: String, required: true },
programItemId: { type: String, required: true },
programItemStartTime: {
type: Date,
get: (value: Date) => new Date(value),
required: true,
},
// No getter: absent on every event log item but a batched lottery's rejection, and a getter
// would turn that absence into an Invalid Date on the toObject/toJSON path
lastProgramItemEndTime: { type: Date },
programType: { type: String },
isSeen: { type: Boolean, required: true },
createdAt: { type: Date, get: (value: Date) => new Date(value) },
},
{
virtuals: {
eventLogItemId: {
get(this: { _id: ObjectId }) {
return this._id;
},
},
},
},
);
const userSchema = new mongoose.Schema(
{
// No `required`: "" is the meaningful value for a local account, and the
// global validator override that lets empty strings satisfy `required`
// only loads with the Express app - tests connecting straight to the DB
// would reject every local account. The default covers the undefined case.
kompassiId: { type: String, default: "" },
kompassiUsernameAccepted: { type: Boolean, required: true },
// Usernames identify a user everywhere: sign-ups, event log writes and
// assignment results all match on this field, and a username-filtered update
// only ever reaches one document. A second document with the same name would
// silently collect writes meant for the other.
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
userGroup: { type: String, required: true },
serial: { type: String, required: true },
isGroupCreator: { type: Boolean, required: true },
groupCode: { type: String, required: true },
favoriteProgramItemIds: { type: [String], required: true },
lotterySignups: { type: [lotterySignupSchema], required: true },
eventLogItems: { type: [eventLogItemSchema], required: true },
email: { type: String, required: false },
emailNotificationPermitAsked: { type: Boolean, required: true },
createdAt: {
type: Date,
get: (value: Date) => new Date(value),
},
},
{
timestamps: true,
},
);
// One Konsti account per Kompassi identity, and an index for the lookup every
// Kompassi login does. Partial so it ignores the "" local accounts share,
// which would otherwise all collide with each other.
userSchema.index(
{ kompassiId: 1 },
{ unique: true, partialFilterExpression: { kompassiId: { $gt: "" } } },
);
userSchema.plugin(mongooseLeanVirtuals, {
enabledByDefault: true,
});
export const UserModel = mongoose.model("user", userSchema);
|