| 
									
										
										
										
											2025-07-24 12:09:24 -07:00
										 |  |  | import lurid from '@andyburke/lurid'; | 
					
						
							| 
									
										
										
										
											2025-06-27 17:54:04 -07:00
										 |  |  | import parse_body from '../../../utils/bodyparser.ts'; | 
					
						
							|  |  |  | import { get_session, get_user, require_user } from '../../../utils/prechecks.ts'; | 
					
						
							|  |  |  | import * as CANNED_RESPONSES from '../../../utils/canned_responses.ts'; | 
					
						
							|  |  |  | import { PRECHECK_TABLE } from '../../../utils/prechecks.ts'; | 
					
						
							|  |  |  | import { ROOM, ROOMS } from '../../../models/room.ts'; | 
					
						
							| 
									
										
										
										
											2025-07-24 12:09:24 -07:00
										 |  |  | import { WALK_ENTRY } from '@andyburke/fsdb'; | 
					
						
							| 
									
										
										
										
											2025-06-27 17:54:04 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | export const PRECHECKS: PRECHECK_TABLE = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GET /api/rooms - get rooms
 | 
					
						
							|  |  |  | PRECHECKS.GET = [get_session, get_user, require_user, (_req: Request, meta: Record<string, any>): Response | undefined => { | 
					
						
							| 
									
										
										
										
											2025-07-01 15:37:35 -07:00
										 |  |  | 	const can_read_rooms = meta.user.permissions.includes('rooms.read'); | 
					
						
							| 
									
										
										
										
											2025-06-27 17:54:04 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!can_read_rooms) { | 
					
						
							|  |  |  | 		return CANNED_RESPONSES.permission_denied(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }]; | 
					
						
							|  |  |  | export async function GET(_req: Request, meta: Record<string, any>): Promise<Response> { | 
					
						
							| 
									
										
										
										
											2025-07-01 15:37:35 -07:00
										 |  |  | 	const limit = Math.min(parseInt(meta.query.limit ?? '100'), 100); | 
					
						
							| 
									
										
										
										
											2025-07-04 12:15:06 -07:00
										 |  |  | 	const rooms = (await ROOMS.all({ | 
					
						
							|  |  |  | 		limit, | 
					
						
							|  |  |  | 		filter: (entry: WALK_ENTRY<ROOM>) => { | 
					
						
							|  |  |  | 			// we push our event collections into the rooms, and fsdb
 | 
					
						
							|  |  |  | 			// doesn't yet filter that out in its all() logic
 | 
					
						
							|  |  |  | 			return entry.path.indexOf('/events/') === -1; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-04 13:27:57 -07:00
										 |  |  | 	})).map((room_entry) => room_entry.load()); | 
					
						
							| 
									
										
										
										
											2025-06-27 17:54:04 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return Response.json(rooms, { | 
					
						
							|  |  |  | 		status: 200 | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // POST /api/rooms - Create a room
 | 
					
						
							|  |  |  | PRECHECKS.POST = [get_session, get_user, require_user, (_req: Request, meta: Record<string, any>): Response | undefined => { | 
					
						
							| 
									
										
										
										
											2025-07-01 15:37:35 -07:00
										 |  |  | 	const can_create_rooms = meta.user.permissions.includes('rooms.create'); | 
					
						
							| 
									
										
										
										
											2025-06-27 17:54:04 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!can_create_rooms) { | 
					
						
							|  |  |  | 		return CANNED_RESPONSES.permission_denied(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }]; | 
					
						
							|  |  |  | export async function POST(req: Request, meta: Record<string, any>): Promise<Response> { | 
					
						
							|  |  |  | 	try { | 
					
						
							|  |  |  | 		const now = new Date().toISOString(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		const body = await parse_body(req); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (typeof body.name !== 'string' || body.name.length === 0) { | 
					
						
							|  |  |  | 			return Response.json({ | 
					
						
							|  |  |  | 				error: { | 
					
						
							|  |  |  | 					cause: 'missing_room_name', | 
					
						
							|  |  |  | 					message: 'You must specify a unique name for a room.' | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}, { | 
					
						
							|  |  |  | 				status: 400 | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (body.name.length > 64) { | 
					
						
							|  |  |  | 			return Response.json({ | 
					
						
							|  |  |  | 				error: { | 
					
						
							|  |  |  | 					cause: 'invalid_room_name', | 
					
						
							|  |  |  | 					message: 'Room names must be 64 characters or fewer.' | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}, { | 
					
						
							|  |  |  | 				status: 400 | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		const normalized_name = body.name.toLowerCase(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		const existing_room = (await ROOMS.find({ | 
					
						
							|  |  |  | 			name: normalized_name | 
					
						
							|  |  |  | 		})).shift(); | 
					
						
							|  |  |  | 		if (existing_room) { | 
					
						
							|  |  |  | 			return Response.json({ | 
					
						
							|  |  |  | 				error: { | 
					
						
							|  |  |  | 					cause: 'room_name_conflict', | 
					
						
							|  |  |  | 					message: 'There is already a room with this name.' | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}, { | 
					
						
							|  |  |  | 				status: 400 | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		const room: ROOM = { | 
					
						
							|  |  |  | 			...body, | 
					
						
							|  |  |  | 			id: lurid(), | 
					
						
							|  |  |  | 			creator_id: meta.user.id, | 
					
						
							|  |  |  | 			permissions: { | 
					
						
							|  |  |  | 				read: (body.permissions?.read ?? []), | 
					
						
							|  |  |  | 				write: (body.permissions?.write ?? [meta.user.id]), | 
					
						
							|  |  |  | 				read_events: (body.permissions?.read_events ?? []), | 
					
						
							|  |  |  | 				write_events: (body.permissions?.write_events ?? []) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			timestamps: { | 
					
						
							|  |  |  | 				created: now, | 
					
						
							|  |  |  | 				updated: now, | 
					
						
							|  |  |  | 				archived: undefined | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		await ROOMS.create(room); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return Response.json(room, { | 
					
						
							|  |  |  | 			status: 201 | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 	} catch (error) { | 
					
						
							|  |  |  | 		return Response.json({ | 
					
						
							|  |  |  | 			error: { | 
					
						
							|  |  |  | 				message: (error as Error).message ?? 'Unknown Error!', | 
					
						
							|  |  |  | 				cause: (error as Error).cause ?? 'unknown' | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}, { status: 500 }); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |