2025-10-08 17:38:23 -07:00
|
|
|
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;
|
2025-10-12 16:25:42 -07:00
|
|
|
expires: string;
|
2025-10-08 17:38:23 -07:00
|
|
|
cancelled?: string;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const INVITE_CODES = new FSDB_COLLECTION<INVITE_CODE>({
|
|
|
|
|
name: 'invite_codes',
|
|
|
|
|
indexers: {
|
|
|
|
|
code: new FSDB_INDEXER_SYMLINKS<INVITE_CODE>({
|
|
|
|
|
name: 'code',
|
|
|
|
|
field: 'code',
|
|
|
|
|
organize: by_character
|
|
|
|
|
}),
|
|
|
|
|
creator_id: new FSDB_INDEXER_SYMLINKS<INVITE_CODE>({
|
|
|
|
|
name: 'creator_id',
|
|
|
|
|
field: 'creator_id',
|
|
|
|
|
to_many: true,
|
|
|
|
|
organize: by_lurid
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2025-10-12 16:25:42 -07:00
|
|
|
const MAX_INVITE_EXPIRE_TIME = 28 * 24 * 60 * 60 * 1_000;
|
2025-10-08 17:38:23 -07:00
|
|
|
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.'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-12 16:25:42 -07:00
|
|
|
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.'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-08 17:38:23 -07:00
|
|
|
return errors.length ? errors : undefined;
|
|
|
|
|
}
|