Compare commits
No commits in common. "6500d9a9be75d293991b13d68b57b0458d1be4ee" and "9e8dc14029d4379329e3bfe07d215105e896c869" have entirely different histories.
6500d9a9be
...
9e8dc14029
5 changed files with 5 additions and 57 deletions
|
|
@ -1,9 +1,6 @@
|
||||||
import { by_character, by_lurid } from '@andyburke/fsdb/organizers';
|
import { by_character, by_lurid } from '@andyburke/fsdb/organizers';
|
||||||
import { FSDB_COLLECTION } from '@andyburke/fsdb';
|
import { FSDB_COLLECTION } from '@andyburke/fsdb';
|
||||||
import { FSDB_INDEXER_SYMLINKS } from '@andyburke/fsdb/indexers';
|
import { FSDB_INDEXER_SYMLINKS } from '@andyburke/fsdb/indexers';
|
||||||
import { EMOJI_MAP as JS_EMOJI_MAP } from '../public/js/emojis/en.js';
|
|
||||||
|
|
||||||
const EMOJI_MAP: Record<string, string[]> = JS_EMOJI_MAP;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {object} TIMESTAMPS
|
* @typedef {object} TIMESTAMPS
|
||||||
|
|
@ -113,37 +110,7 @@ export function VALIDATE_EVENT(event: EVENT) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'reaction':
|
|
||||||
if (typeof event.parent_id !== 'string') {
|
|
||||||
errors.push({
|
|
||||||
cause: 'reaction_missing_parent_id',
|
|
||||||
message: 'A reaction must have a parent_id that refers to another event.'
|
|
||||||
});
|
|
||||||
} else if (typeof event.data?.reaction !== 'string') {
|
|
||||||
errors.push({
|
|
||||||
cause: 'reaction_must_be_an_emoji',
|
|
||||||
message: 'A reaction event must have a `data.reaction` that is an emoji.'
|
|
||||||
});
|
|
||||||
} else if (typeof EMOJI_MAP[event.data.reaction] === 'undefined') {
|
|
||||||
errors.push({
|
|
||||||
cause: 'reaction_must_be_an_emoji',
|
|
||||||
message: 'A reaction event must have a `data.reaction` that is an emoji.'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'test':
|
|
||||||
if (Deno.env.get('DENO_ENV') !== 'test') {
|
|
||||||
errors.push({
|
|
||||||
cause: 'unknown_event_type',
|
|
||||||
message: 'Event types allowed: ' + ['chat', 'post', 'blurb', 'essay', 'reaction'].join(', ')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
errors.push({
|
|
||||||
cause: 'unknown_event_type',
|
|
||||||
message: 'Event types allowed: ' + ['chat', 'post', 'blurb', 'essay', 'reaction'].join(', ')
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ export type INVITE_CODE = {
|
||||||
code: string;
|
code: string;
|
||||||
timestamps: {
|
timestamps: {
|
||||||
created: string;
|
created: string;
|
||||||
expires: string;
|
expires?: string;
|
||||||
cancelled?: string;
|
cancelled?: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -30,7 +30,7 @@ export const INVITE_CODES = new FSDB_COLLECTION<INVITE_CODE>({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const MAX_INVITE_EXPIRE_TIME = 28 * 24 * 60 * 60 * 1_000;
|
// TODO: separate out these different validators somewhere?
|
||||||
export function VALIDATE_INVITE_CODE(invite_code: INVITE_CODE) {
|
export function VALIDATE_INVITE_CODE(invite_code: INVITE_CODE) {
|
||||||
const errors: any[] = [];
|
const errors: any[] = [];
|
||||||
|
|
||||||
|
|
@ -41,6 +41,7 @@ export function VALIDATE_INVITE_CODE(invite_code: INVITE_CODE) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: further invite code validation
|
||||||
if (typeof invite_code.code !== 'string' || invite_code.id.length < 3) {
|
if (typeof invite_code.code !== 'string' || invite_code.id.length < 3) {
|
||||||
errors.push({
|
errors.push({
|
||||||
cause: 'invalid_invite_code_code',
|
cause: 'invalid_invite_code_code',
|
||||||
|
|
@ -48,20 +49,5 @@ export function VALIDATE_INVITE_CODE(invite_code: INVITE_CODE) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
return errors.length ? errors : undefined;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import { INVITE_CODE, INVITE_CODES, VALIDATE_INVITE_CODE } from '../../../../../
|
||||||
export const PRECHECKS: PRECHECK_TABLE = {};
|
export const PRECHECKS: PRECHECK_TABLE = {};
|
||||||
|
|
||||||
const INVITE_CODES_ALLOWED_PER_MINUTE = parseInt(Deno.env.get('INVITE_CODES_ALLOWED_PER_MINUTE') ?? '3', 10);
|
const INVITE_CODES_ALLOWED_PER_MINUTE = parseInt(Deno.env.get('INVITE_CODES_ALLOWED_PER_MINUTE') ?? '3', 10);
|
||||||
const DEFAULT_INVITE_EXPIRE_TIME: number = 28 * 24 * 60 * 60 * 1_000; // 28 days max invite length
|
|
||||||
|
|
||||||
// GET /api/users/:user_id/invites - get invites this user has created
|
// GET /api/users/:user_id/invites - get invites this user has created
|
||||||
// query parameters:
|
// query parameters:
|
||||||
|
|
@ -95,8 +94,6 @@ export async function POST(req: Request, meta: Record<string, any>): Promise<Res
|
||||||
invite_code.code = `${full_lurid.substring(0, 14).replace(/-/g, ' ')}${full_lurid.substring(39).replace(/-/g, ' ')}`;
|
invite_code.code = `${full_lurid.substring(0, 14).replace(/-/g, ' ')}${full_lurid.substring(39).replace(/-/g, ' ')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
invite_code.timestamps.expires = invite_code.timestamps.expires ?? new Date(new Date(now).valueOf() + DEFAULT_INVITE_EXPIRE_TIME).toISOString();
|
|
||||||
|
|
||||||
const errors = VALIDATE_INVITE_CODE(invite_code);
|
const errors = VALIDATE_INVITE_CODE(invite_code);
|
||||||
if (errors) {
|
if (errors) {
|
||||||
return Response.json({
|
return Response.json({
|
||||||
|
|
|
||||||
|
|
@ -128,8 +128,7 @@ export async function POST(req: Request, meta: Record<string, any>): Promise<Res
|
||||||
code: root_invite_code_secret,
|
code: root_invite_code_secret,
|
||||||
creator_id: new_user_id,
|
creator_id: new_user_id,
|
||||||
timestamps: {
|
timestamps: {
|
||||||
created: now,
|
created: now
|
||||||
expires: new Date(new Date(now).valueOf() + 1_000).toISOString()
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -152,7 +151,7 @@ export async function POST(req: Request, meta: Record<string, any>): Promise<Res
|
||||||
code: secret_code
|
code: secret_code
|
||||||
})).shift()?.load();
|
})).shift()?.load();
|
||||||
|
|
||||||
const is_expired = now >= (invite_code?.timestamps.expires ?? '0000-01-01T00:00:00.000Z');
|
const is_expired = invite_code?.timestamps.expires ? now <= invite_code.timestamps.expires : false;
|
||||||
const is_used = (await SIGNUPS.find({
|
const is_used = (await SIGNUPS.find({
|
||||||
referring_invite_code_id: invite_code?.id
|
referring_invite_code_id: invite_code?.id
|
||||||
}, {
|
}, {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#chat #chat-content {
|
#chat #chat-content {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
scroll-behavior: smooth;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue