55const corsHeaders = {
66 'Access-Control-Allow-Origin' : 'https://analytics.ujjwalvivek.com' ,
77 'Access-Control-Allow-Methods' : 'GET, POST, OPTIONS' ,
8- 'Access-Control-Allow-Headers' : 'Content-Type, Authorization' ,
8+ 'Access-Control-Allow-Headers' : 'Content-Type, Authorization, X-API-Key ' ,
99 'Access-Control-Max-Age' : '86400' ,
1010} ;
1111
@@ -39,6 +39,21 @@ function validateEvent(event) {
3939 return event ;
4040}
4141
42+ // Validate API key for dashboard access
43+ function validateApiKey ( request , env ) {
44+ const authHeader = request . headers . get ( 'Authorization' ) ;
45+ if ( ! authHeader || ! authHeader . startsWith ( 'Bearer ' ) ) {
46+ return false ;
47+ }
48+
49+ const apiKey = authHeader . substring ( 7 ) ; // Remove "Bearer " prefix
50+
51+ // Use environment variable for API key (set in Cloudflare dashboard)
52+ const validApiKey = env . ANALYTICS_API_KEY ;
53+
54+ return apiKey === validApiKey ;
55+ }
56+
4257// Store event in R2 bucket (organized by date)
4358async function storeEvent ( event , env ) {
4459 const date = new Date ( event . timestamp ) ;
@@ -81,6 +96,14 @@ async function isRateLimited(hashedIP, env) {
8196
8297async function handleDashboardData ( request , env ) {
8398 try {
99+ // Validate API key for dashboard access
100+ if ( ! validateApiKey ( request , env ) ) {
101+ return new Response ( 'Unauthorized' , {
102+ status : 401 ,
103+ headers : corsHeaders
104+ } ) ;
105+ }
106+
84107 // Get query parameters
85108 const url = new URL ( request . url ) ;
86109 const range = url . searchParams . get ( 'range' ) || '7d' ;
@@ -113,7 +136,12 @@ async function handleDashboardData(request, env) {
113136 } ) ;
114137 } catch ( error ) {
115138 console . error ( 'Dashboard data error:' , error ) ;
116- return new Response ( JSON . stringify ( { error : 'Failed to fetch analytics data' } ) , {
139+ console . error ( 'Error stack:' , error . stack ) ;
140+ return new Response ( JSON . stringify ( {
141+ error : 'Failed to fetch analytics data' ,
142+ details : error . message ,
143+ stack : error . stack
144+ } ) , {
117145 status : 500 ,
118146 headers : {
119147 ...corsHeaders ,
@@ -124,6 +152,7 @@ async function handleDashboardData(request, env) {
124152}
125153
126154async function getAnalyticsFromR2 ( env , startDate , endDate ) {
155+ console . log ( 'Getting analytics data from R2...' ) ;
127156 // For now, return minimal real data structure
128157 // You can expand this to actually read from R2 later
129158 const events = [ ] ;
@@ -132,8 +161,10 @@ async function getAnalyticsFromR2(env, startDate, endDate) {
132161 try {
133162 const today = new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] ;
134163 const prefix = `analytics/${ today } /` ;
164+ console . log ( 'Listing R2 objects with prefix:' , prefix ) ;
135165
136166 const list = await env . analytics_data . list ( { prefix, limit : 100 } ) ;
167+ console . log ( 'Found objects:' , list . objects . length ) ;
137168
138169 for ( const object of list . objects ) {
139170 try {
@@ -144,12 +175,13 @@ async function getAnalyticsFromR2(env, startDate, endDate) {
144175 events . push ( event ) ;
145176 }
146177 } catch ( e ) {
178+ console . error ( 'Error parsing event:' , e ) ;
147179 // Skip invalid events
148180 continue ;
149181 }
150182 }
151183 } catch ( error ) {
152- console . log ( 'No analytics data found yet' ) ;
184+ console . error ( 'Error reading from R2:' , error ) ;
153185 }
154186
155187 // Process events into dashboard data
@@ -235,14 +267,14 @@ const worker = {
235267 return new Response ( null , { headers : corsHeaders } ) ;
236268 }
237269
238- // Route handling
270+ // Route handling for analytics.ujjwalvivek.com/api
239271 if ( url . pathname === '/api' && request . method === 'POST' ) {
240272 // Analytics data collection endpoint
241273 return handleAnalyticsCollection ( request , env ) ;
242274 } else if ( url . pathname === '/api' && request . method === 'GET' ) {
243275 // Dashboard data endpoint
244276 return handleDashboardData ( request , env ) ;
245- } else if ( url . pathname === '/dashboard' && request . method === 'GET' ) {
277+ } else if ( url . pathname === '/api/ dashboard' && request . method === 'GET' ) {
246278 // Dashboard data endpoint (future feature)
247279 return new Response ( 'Dashboard API endpoint' , { headers : corsHeaders } ) ;
248280 } else {
0 commit comments