import { FSDB_COLLECTION } from '@andyburke/fsdb'; import { FSDB_INDEXER_SYMLINKS } from '@andyburke/fsdb/indexers'; import { by_character, by_lurid } from '@andyburke/fsdb/organizers'; export type INVITE_CODE = { id: string; creator_id: string; code: string; timestamps: { created: string; expires: string; cancelled?: string; }; }; export const INVITE_CODES = new FSDB_COLLECTION({ name: 'invite_codes', indexers: { code: new FSDB_INDEXER_SYMLINKS({ name: 'code', field: 'code', organize: by_character }), creator_id: new FSDB_INDEXER_SYMLINKS({ name: 'creator_id', field: 'creator_id', to_many: true, organize: by_lurid }) } }); const MAX_INVITE_EXPIRE_TIME = 28 * 24 * 60 * 60 * 1_000; export function VALIDATE_INVITE_CODE(invite_code: INVITE_CODE) { const errors: any[] = []; if (typeof invite_code.id !== 'string' || invite_code.id.length !== 49) { errors.push({ cause: 'invalid_invite_code_id', message: 'An invite code must have a lurid id, eg: able-fish-gold-wing-trip-form-seed-cost-rope-wife' }); } if (typeof invite_code.code !== 'string' || invite_code.id.length < 3) { errors.push({ cause: 'invalid_invite_code_code', message: 'An invite code must have a secret code that is at least 3 characters long.' }); } if (typeof invite_code.timestamps?.expires !== 'string') { errors.push({ cause: 'missing_invite_expiration', message: 'Invite codes must have an expiration set.' }); } const expiration_delta = new Date(invite_code.timestamps.expires).valueOf() - new Date(invite_code.timestamps.created).valueOf(); if (expiration_delta > MAX_INVITE_EXPIRE_TIME || expiration_delta < 0) { errors.push({ cause: 'invite_expiration_invalid', message: 'Invite codes must expire within a limited window after they are created.' }); } return errors.length ? errors : undefined; }