@@ -4,13 +4,29 @@ const express = require('express');
44const { createProxyMiddleware } = require ( 'http-proxy-middleware' ) ;
55const { createPublicClient, http } = require ( 'viem' ) ;
66const { gnosis } = require ( 'viem/chains' ) ;
7+ const crypto = require ( 'crypto' ) ;
78
89// Add this near the top with other environment variables
910const PORT = process . env . PORT || 3333 ;
1011const PROXY_TARGET = process . env . PROXY_TARGET || 'http://localhost:1633' ;
1112const REGISTRY_ADDRESS =
1213 process . env . REGISTRY_ADDRESS || '0x5EBfBeFB1E88391eFb022d5d33302f50a46bF4f3' ;
1314
15+ // Session management for multi-file uploads
16+ const uploadSessions = new Map ( ) ;
17+ const SESSION_DURATION = 15 * 60 * 1000 ; // 15 minutes
18+ const SESSION_CLEANUP_INTERVAL = 5 * 60 * 1000 ; // 5 minutes
19+
20+ // Clean up expired sessions periodically
21+ setInterval ( ( ) => {
22+ const now = Date . now ( ) ;
23+ for ( const [ sessionId , session ] of uploadSessions . entries ( ) ) {
24+ if ( now - session . createdAt > SESSION_DURATION ) {
25+ uploadSessions . delete ( sessionId ) ;
26+ }
27+ }
28+ } , SESSION_CLEANUP_INTERVAL ) ;
29+
1430const BATCH_REGISTRY_ABI = [
1531 {
1632 name : 'getBatchPayer' ,
@@ -28,6 +44,35 @@ const gnosisPublicClient = createPublicClient({
2844 transport : http ( ) ,
2945} ) ;
3046
47+ // Generate a secure session token
48+ const generateSessionToken = ( uploaderAddress , batchId ) => {
49+ const data = `${ uploaderAddress } :${ batchId } :${ Date . now ( ) } :${ crypto . randomBytes ( 16 ) . toString ( 'hex' ) } ` ;
50+ return crypto . createHash ( 'sha256' ) . update ( data ) . digest ( 'hex' ) ;
51+ } ;
52+
53+ // Check if there's a valid session for this upload
54+ const checkExistingSession = ( uploaderAddress , batchId , sessionToken ) => {
55+ if ( ! sessionToken ) return null ;
56+
57+ const session = uploadSessions . get ( sessionToken ) ;
58+ if ( ! session ) return null ;
59+
60+ const now = Date . now ( ) ;
61+ if ( now - session . createdAt > SESSION_DURATION ) {
62+ uploadSessions . delete ( sessionToken ) ;
63+ return null ;
64+ }
65+
66+ if (
67+ session . uploaderAddress . toLowerCase ( ) !== uploaderAddress . toLowerCase ( ) ||
68+ session . batchId !== batchId
69+ ) {
70+ return null ;
71+ }
72+
73+ return session ;
74+ } ;
75+
3176const verifySignature = async ( req , res , next ) => {
3277 console . log ( 'Processing request at path:' , req . path ) ;
3378
@@ -39,15 +84,38 @@ const verifySignature = async (req, res, next) => {
3984 const fileName = req . headers [ 'x-file-name' ] ;
4085 const batchId = req . headers [ 'swarm-postage-batch-id' ] ;
4186 const messageContent = req . headers [ 'x-message-content' ] ;
87+ const sessionToken = req . headers [ 'x-upload-session-token' ] ; // New header for session token
88+ const isMultiFileUpload = req . headers [ 'x-multi-file-upload' ] === 'true' ; // New header to indicate multi-file upload
4289
4390 console . log ( 'Headers received:' , {
4491 signedMessage : signedMessage ? 'exists' : 'missing' ,
4592 uploaderAddress,
4693 fileName,
4794 batchId,
4895 messageContent,
96+ sessionToken : sessionToken ? 'exists' : 'missing' ,
97+ isMultiFileUpload,
4998 } ) ;
5099
100+ // Check for existing session first (for multi-file uploads)
101+ if ( sessionToken && uploaderAddress && batchId ) {
102+ const existingSession = checkExistingSession ( uploaderAddress , batchId , sessionToken ) ;
103+ if ( existingSession ) {
104+ console . log ( 'Valid session found, skipping detailed verification' ) ;
105+ // Update session last used time
106+ existingSession . lastUsed = Date . now ( ) ;
107+ existingSession . fileCount += 1 ;
108+
109+ // Add session info to response headers for client
110+ res . setHeader ( 'x-session-token' , sessionToken ) ;
111+ res . setHeader ( 'x-session-valid' , 'true' ) ;
112+ return next ( ) ;
113+ } else {
114+ console . log ( 'Invalid or expired session token provided' ) ;
115+ }
116+ }
117+
118+ // Full verification required (first file or no valid session)
51119 if ( ! signedMessage || ! uploaderAddress || ! fileName || ! batchId ) {
52120 return res . status ( 401 ) . json ( {
53121 error : 'Missing required headers' ,
@@ -118,6 +186,27 @@ const verifySignature = async (req, res, next) => {
118186 }
119187
120188 console . log ( 'Verification successful' ) ;
189+
190+ // Create session token for multi-file uploads
191+ if ( isMultiFileUpload ) {
192+ const newSessionToken = generateSessionToken ( uploaderAddress , batchId ) ;
193+ uploadSessions . set ( newSessionToken , {
194+ uploaderAddress,
195+ batchId,
196+ createdAt : Date . now ( ) ,
197+ lastUsed : Date . now ( ) ,
198+ fileCount : 1 ,
199+ } ) ;
200+
201+ console . log (
202+ `Created new session token for multi-file upload: ${ newSessionToken . substring ( 0 , 8 ) } ...`
203+ ) ;
204+
205+ // Add session token to response headers
206+ res . setHeader ( 'x-session-token' , newSessionToken ) ;
207+ res . setHeader ( 'x-session-created' , 'true' ) ;
208+ }
209+
121210 next ( ) ;
122211 } catch ( error ) {
123212 console . error ( 'Verification Error:' , error ) ;
0 commit comments