tunnel/source/server/routes/tunnels.ts

79 lines
2.6 KiB
TypeScript
Raw Normal View History

2026-07-16 12:17:00 +00:00
import { Router } from 'express';
import { requireAuth } from '../middleware/requireAuth';
import * as db from '../db';
import { registry } from '../relay/TunnelRegistry';
const router = Router();
router.post( '/', requireAuth, ( req, res ) =>
{
const { name, description, purpose, access, allowedUserIds, localPort } = req.body;
if ( !name || !purpose || !localPort )
{
res.status( 400 ).json( { error: 'name, purpose, and localPort are required' } );
return;
}
const tunnel = db.createTunnel( {
name,
description: description ?? '',
purpose,
ownerId: req.auth!.userId,
access: access === 'public' ? 'public' : 'private',
allowedUserIds: Array.isArray( allowedUserIds ) ? allowedUserIds : [],
localPort: Number( localPort ),
} );
res.status( 201 ).json( tunnel );
} );
router.get( '/', requireAuth, ( _req, res ) =>
{
const tunnels = db.getTunnelsByOwner( _req.auth!.userId ).map( t => ( {
...t,
active: registry.isActive( t.id ),
} ) );
res.json( tunnels );
} );
router.get( '/available', requireAuth, ( req, res ) =>
{
const purpose = typeof req.query.purpose === 'string' ? req.query.purpose : undefined;
const tunnels = db.getAvailableTunnels( req.auth!.userId, purpose ).map( t => ( {
...t,
active: registry.isActive( t.id ),
} ) );
res.json( tunnels );
} );
router.get( '/:id', requireAuth, ( req, res ) =>
{
const tunnel = db.getTunnel( req.params.id );
if ( !tunnel ) { res.status( 404 ).json( { error: 'Not found' } ); return; }
const userId = req.auth!.userId;
if ( tunnel.ownerId !== userId && !tunnel.allowedUserIds.includes( userId ) )
{
res.status( 403 ).json( { error: 'Forbidden' } ); return;
}
res.json( { ...tunnel, active: registry.isActive( tunnel.id ) } );
} );
router.patch( '/:id', requireAuth, ( req, res ) =>
{
const tunnel = db.getTunnel( req.params.id );
if ( !tunnel ) { res.status( 404 ).json( { error: 'Not found' } ); return; }
if ( tunnel.ownerId !== req.auth!.userId ) { res.status( 403 ).json( { error: 'Forbidden' } ); return; }
const { name, description, access, allowedUserIds, purpose } = req.body;
const updated = db.updateTunnel( req.params.id, { name, description, access, allowedUserIds, purpose } );
res.json( updated );
} );
router.delete( '/:id', requireAuth, ( req, res ) =>
{
const tunnel = db.getTunnel( req.params.id );
if ( !tunnel ) { res.status( 404 ).json( { error: 'Not found' } ); return; }
if ( tunnel.ownerId !== req.auth!.userId ) { res.status( 403 ).json( { error: 'Forbidden' } ); return; }
db.deleteTunnel( req.params.id );
res.status( 204 ).end();
} );
export default router;