@@ -2,54 +2,75 @@ import { NextRequest } from 'next/server';
22import { jsonResponse } from '@/lib/apiHandler' ;
33import { createAPIRoute } from '@/lib/routeHelper' ;
44import { validateSealId } from '@/lib/validation' ;
5- import { isHoneypot } from '@/lib/security' ;
5+ import { isHoneypot , validateHTTPMethod , validateOrigin , concurrentTracker , detectSuspiciousPattern } from '@/lib/security' ;
66import { logger } from '@/lib/logger' ;
77
88
99export async function GET (
1010 request : NextRequest ,
1111 { params } : { params : Promise < { id : string } > }
1212) {
13- return createAPIRoute ( async ( { container, ip } ) => {
14- const { id : sealId } = await params ;
13+ if ( ! validateHTTPMethod ( request , [ 'GET' ] ) ) {
14+ return jsonResponse ( { error : 'Method not allowed' } , 405 ) ;
15+ }
1516
16- const sealIdValidation = validateSealId ( sealId ) ;
17- if ( ! sealIdValidation . valid ) {
18- return jsonResponse ( { error : sealIdValidation . error } , 400 ) ;
19- }
17+ if ( ! validateOrigin ( request ) ) {
18+ return jsonResponse ( { error : 'Invalid origin' } , 403 ) ;
19+ }
2020
21- if ( isHoneypot ( sealId ) ) {
22- logger . warn ( 'honeypot_accessed' , { ip, sealId, userAgent : request . headers . get ( 'user-agent' ) } ) ;
23- return jsonResponse ( {
24- id : sealId ,
25- isLocked : true ,
26- unlockTime : Date . now ( ) + 999999999999 ,
27- timeRemaining : 999999999999 ,
28- } ) ;
21+ return createAPIRoute ( async ( { container, ip } ) => {
22+ if ( ! concurrentTracker . track ( ip ) ) {
23+ return jsonResponse ( { error : 'Too many concurrent requests' } , 429 ) ;
2924 }
30- const sealService = container . sealService ;
31- const metadata = await sealService . getSeal ( sealId , ip ) ;
3225
33- if ( metadata . status === 'locked' ) {
26+ try {
27+ const { id : sealId } = await params ;
28+
29+ const sealIdValidation = validateSealId ( sealId ) ;
30+ if ( ! sealIdValidation . valid ) {
31+ return jsonResponse ( { error : sealIdValidation . error } , 400 ) ;
32+ }
33+
34+ if ( detectSuspiciousPattern ( ip , sealId ) ) {
35+ logger . warn ( 'suspicious_pattern' , { ip, sealId } ) ;
36+ }
37+
38+ if ( isHoneypot ( sealId ) ) {
39+ logger . warn ( 'honeypot_accessed' , { ip, sealId, userAgent : request . headers . get ( 'user-agent' ) } ) ;
40+ return jsonResponse ( {
41+ id : sealId ,
42+ isLocked : true ,
43+ unlockTime : Date . now ( ) + 999999999999 ,
44+ timeRemaining : 999999999999 ,
45+ } ) ;
46+ }
47+
48+ const sealService = container . sealService ;
49+ const metadata = await sealService . getSeal ( sealId , ip ) ;
50+
51+ if ( metadata . status === 'locked' ) {
52+ return jsonResponse ( {
53+ id : sealId ,
54+ isLocked : true ,
55+ unlockTime : metadata . unlockTime ,
56+ timeRemaining : metadata . unlockTime - Date . now ( ) ,
57+ } ) ;
58+ }
59+
60+ const blob = await sealService . getBlob ( sealId ) ;
61+ const bytes = new Uint8Array ( blob ) ;
62+ const blobBase64 = btoa ( String . fromCharCode ( ...bytes ) ) ;
63+
3464 return jsonResponse ( {
3565 id : sealId ,
36- isLocked : true ,
66+ isLocked : false ,
3767 unlockTime : metadata . unlockTime ,
38- timeRemaining : metadata . unlockTime - Date . now ( ) ,
68+ keyB : metadata . keyB ,
69+ iv : metadata . iv ,
70+ encryptedBlob : blobBase64 ,
3971 } ) ;
72+ } finally {
73+ concurrentTracker . release ( ip ) ;
4074 }
41-
42- const blob = await sealService . getBlob ( sealId ) ;
43- const bytes = new Uint8Array ( blob ) ;
44- const blobBase64 = btoa ( String . fromCharCode ( ...bytes ) ) ;
45-
46- return jsonResponse ( {
47- id : sealId ,
48- isLocked : false ,
49- unlockTime : metadata . unlockTime ,
50- keyB : metadata . keyB ,
51- iv : metadata . iv ,
52- encryptedBlob : blobBase64 ,
53- } ) ;
5475 } , { rateLimit : { limit : 20 , window : 60000 } } ) ( request ) ;
5576}
0 commit comments