2025-06-25 20:51:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  {  get_session ,  get_user ,  PRECHECK_TABLE ,  require_user  }  from  '../../../../utils/prechecks.ts' ;  
						 
					
						
							
								
									
										
										
										
											2025-06-24 16:17:00 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  {  PASSWORD_ENTRIES ,  PASSWORD_ENTRY  }  from  '../../../../models/password_entry.ts' ;  
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  {  SESSIONS  }  from  '../../../../models/session.ts' ;  
						 
					
						
							
								
									
										
										
										
											2025-06-24 16:17:00 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  {  USER ,  USERS  }  from  '../../../../models/user.ts' ;  
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  parse_body  from  '../../../../utils/bodyparser.ts' ;  
						 
					
						
							
								
									
										
										
										
											2025-06-27 17:54:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  *  as  CANNED_RESPONSES  from  '../../../../utils/canned_responses.ts' ;  
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-25 20:51:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								export  const  PRECHECKS : PRECHECK_TABLE  =  { } ;  
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GET /api/users/:id - Get single user
  
						 
					
						
							
								
									
										
										
										
											2025-06-25 20:51:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								PRECHECKS . GET  =  [ get_session ,  get_user ,  require_user ,  ( _req : Request ,  meta : Record < string ,  any > ) :  Response  |  undefined  = >  {  
						 
					
						
							
								
									
										
										
										
											2025-06-27 17:54:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  user_is_self  =  ! ! meta . user  &&  ! ! meta . params  &&  meta . user . id  ===  meta . params . user_id ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  can_read_self  =  meta . user ? . permissions . includes ( 'self.read' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  can_read_others  =  meta . user ? . permissions ? . includes ( 'users.read' ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-25 20:51:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  has_permission  =  can_read_others  ||  ( can_read_self  &&  user_is_self ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! has_permission )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CANNED_RESPONSES . permission_denied ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ] ;  
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								export  async  function  GET ( _req : Request ,  meta : Record < string ,  any > ) :  Promise < Response >  {  
						 
					
						
							
								
									
										
										
										
											2025-06-27 17:54:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  user_id : string  =  meta . params ? . user_id ? . toLowerCase ( ) . trim ( )  ? ?  '' ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 16:17:00 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  user : USER  |  null  =  user_id . length  ===  49  ?  await  USERS . get ( user_id )  :  null ;  // lurid is 49 chars as we use them, eg: "also-play-flow-want-form-wide-thus-work-burn-same"
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! user )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  Response . json ( { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											error :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												message :  ` Could not locate a user with id: " ${ user_id } " ` , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cause :  'unknown_user' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ,  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status : 404 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  Response . json ( user ,  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status : 200 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// PUT /api/users/:id - Update user
  
						 
					
						
							
								
									
										
										
										
											2025-06-27 17:54:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								PRECHECKS . PUT  =  [ get_session ,  get_user ,  require_user ,  ( req : Request ,  meta : Record < string ,  any > ) :  Response  |  undefined  = >  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  user_is_self  =  ! ! meta . user  &&  ! ! meta . params  &&  meta . user . id  ===  meta . params . user_id ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  can_write_self  =  meta . user ? . permissions . includes ( 'self.write' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  can_write_others  =  meta . user ? . permissions ? . includes ( 'users.write' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  is_a_test_override  =  Deno . env . get ( 'DENO_ENV' )  ===  'test'  &&  ! ! req . headers . get ( 'x-test-override' ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-27 17:54:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  has_permission  =  is_a_test_override  ||  can_write_others  ||  ( can_write_self  &&  user_is_self ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-25 20:51:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! has_permission )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CANNED_RESPONSES . permission_denied ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ] ;  
						 
					
						
							
								
									
										
										
										
											2025-06-27 17:54:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								export  async  function  PUT ( req : Request ,  meta : Record < string ,  any > ) :  Promise < Response >  {  
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									const  now  =  new  Date ( ) . toISOString ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-27 17:54:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  id : string  =  meta . params . user_id  ? ?  '' ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 16:17:00 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  existing  =  await  USERS . get ( id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! existing )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  Response . json ( { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											error :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												message :  'User not found' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cause :  'unknown_user' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ,  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status : 404 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									try  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  body  =  await  parse_body ( req ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-27 17:54:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										const  updated : USER  =  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											. . . existing , 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-27 17:54:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											. . . body , 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											timestamps :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												created : existing.timestamps.created , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												updated : now 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-27 17:54:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( Array . isArray ( body . permissions )  &&  body . permissions . join ( ':' )  !==  existing . permissions . join ( ':' ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											const  user_can_write_others  =  meta . user . permissions . includes ( 'users.write' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											const  is_a_test_override  =  Deno . env . get ( 'DENO_ENV' )  ===  'test'  &&  req . headers . get ( 'x-test-override' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											const  is_allowed  =  user_can_write_others  ||  is_a_test_override ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! is_allowed )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  CANNED_RESPONSES . permission_denied ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 16:17:00 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										await  USERS . update ( updated ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  Response . json ( updated ,  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status : 200 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  catch  ( err )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  Response . json ( { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											error :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												message :  ( err  as  Error ) ? . message  ? ?  'Unknown error due to invalid user data.' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cause :  ( err  as  Error ) ? . cause  ? ?  'invalid_user_data' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ,  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status : 400 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// DELETE /api/users/:id - Delete user
  
						 
					
						
							
								
									
										
										
										
											2025-06-25 20:51:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								PRECHECKS . DELETE  =  [ get_session ,  get_user ,  require_user ,  ( _req : Request ,  meta : Record < string ,  any > ) :  Response  |  undefined  = >  {  
						 
					
						
							
								
									
										
										
										
											2025-06-27 17:54:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  user_is_self  =  ! ! meta . user  &&  ! ! meta . params  &&  meta . user . id  ===  meta . params . user_id ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  can_write_self  =  meta . user ? . permissions . includes ( 'self.write' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  can_write_others  =  meta . user ? . permissions ? . includes ( 'users.write' ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-25 20:51:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  has_permission  =  can_write_others  ||  ( can_write_self  &&  user_is_self ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! has_permission )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CANNED_RESPONSES . permission_denied ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ] ;  
						 
					
						
							
								
									
										
										
										
											2025-06-27 17:54:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								export  async  function  DELETE ( _req : Request ,  meta : Record < string ,  any > ) :  Promise < Response >  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  user_id : string  =  meta . params . user_id  ? ?  '' ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 16:17:00 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  user : USER  |  null  =  await  USERS . get ( user_id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ( ! user )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  Response . json ( { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											error :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												message :  'Error deleting user.' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cause :  'unknown_user' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ,  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status : 404 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 16:17:00 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  password_entry : PASSWORD_ENTRY  |  null  =  await  PASSWORD_ENTRIES . get ( user_id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ( password_entry )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 16:17:00 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										await  PASSWORD_ENTRIES . delete ( password_entry ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-07-02 21:28:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  session_entries  =  await  SESSIONS . find ( { 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										user_id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-07-02 21:28:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ( const  entry  of  session_entries )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										await  SESSIONS . delete ( entry . load ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 16:17:00 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									await  USERS . delete ( user ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 15:40:30 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  Response . json ( { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										deleted : true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ,  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status : 200 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}