Skip to content

Commit 76e8786

Browse files
committed
clean up ip-geo
1 parent d01ae59 commit 76e8786

File tree

7 files changed

+123
-83
lines changed

7 files changed

+123
-83
lines changed

apps/basket/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const app = new Elysia()
1515
)
1616
);
1717
})
18-
.onBeforeHandle(async ({ request, set }) => {
18+
.onBeforeHandle(({ request, set }) => {
1919
// const { isBot } = await checkBotId();
2020
// if (isBot) {
2121
// return new Response(null, { status: 403 });

apps/basket/src/routes/stripe.ts

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { clickHouse, db, eq, userStripeConfig } from '@databuddy/db';
22
import { Elysia } from 'elysia';
33
import Stripe from 'stripe';
4+
import { logger } from '../lib/logger';
45

56
/**
67
* STRIPE CHECKOUT SETUP GUIDE
@@ -102,10 +103,9 @@ async function getStripeConfigByToken(
102103
isLiveMode: config.isLiveMode,
103104
};
104105
} catch (error) {
105-
console.error(
106-
`Error fetching Stripe config for token ${webhookToken}:`,
107-
error
108-
);
106+
logger.error(`Error fetching Stripe config for token ${webhookToken}`, {
107+
error: error instanceof Error ? error.message : 'Unknown error',
108+
});
109109
return null;
110110
}
111111
}
@@ -145,23 +145,32 @@ async function handleWebhook(request: Request, set: any, config: StripeConfig) {
145145
return { error: 'Live/test mode mismatch' };
146146
}
147147

148-
console.log(`📦 Stripe webhook received for user ${config.userId}:`, {
148+
logger.info(`📦 Stripe webhook received for user ${config.userId}:`, {
149149
type: event.type,
150150
id: event.id,
151151
livemode: event.livemode,
152152
});
153153

154154
try {
155155
await processWebhookEvent(event, config);
156-
console.log(`✅ Successfully processed ${event.type}`);
156+
logger.info(`✅ Successfully processed ${event.type}`);
157157
} catch (processingError) {
158-
console.error('❌ Error processing webhook event:', processingError);
158+
logger.error('❌ Error processing webhook event:', {
159+
error:
160+
processingError instanceof Error
161+
? processingError.message
162+
: 'Unknown error',
163+
});
164+
set.status = 500;
165+
return { error: 'Error processing webhook event' };
159166
}
160167

161168
set.status = 200;
162169
return { received: true, eventType: event.type };
163170
} catch (err) {
164-
console.error('⚠️ Webhook signature verification failed:', err);
171+
logger.error('⚠️ Webhook signature verification failed:', {
172+
error: err instanceof Error ? err.message : 'Unknown error',
173+
});
165174
logSecurityEvent(
166175
'signature_verification_failed',
167176
config.webhookToken,
@@ -203,7 +212,7 @@ async function processWebhookEvent(event: Stripe.Event, config: StripeConfig) {
203212
if (handler) {
204213
await handler(event.data.object as any);
205214
} else {
206-
console.log(`🔄 Unhandled event type: ${event.type}`);
215+
logger.info(`🔄 Unhandled event type: ${event.type}`);
207216
}
208217
}
209218

@@ -274,7 +283,7 @@ async function insertPaymentIntent(
274283
session_id: sessionId,
275284
});
276285

277-
console.log(`✅ PaymentIntent ${pi.id} processed for client ${clientId}`);
286+
logger.info(`✅ PaymentIntent ${pi.id} processed for client ${clientId}`);
278287
}
279288

280289
async function insertCharge(charge: Stripe.Charge, config: StripeConfig) {
@@ -309,7 +318,7 @@ async function insertCharge(charge: Stripe.Charge, config: StripeConfig) {
309318
session_id: sessionId,
310319
});
311320

312-
console.log(`✅ Charge ${charge.id} processed for client ${clientId}`);
321+
logger.info(`✅ Charge ${charge.id} processed for client ${clientId}`);
313322
}
314323

315324
async function insertRefund(refund: Stripe.Refund, config: StripeConfig) {
@@ -336,7 +345,7 @@ async function insertRefund(refund: Stripe.Refund, config: StripeConfig) {
336345
session_id: sessionId,
337346
});
338347

339-
console.log(`✅ Refund ${refund.id} processed for client ${clientId}`);
348+
logger.info(`✅ Refund ${refund.id} processed for client ${clientId}`);
340349
}
341350

342351
function logSecurityEvent(
@@ -353,12 +362,9 @@ function logSecurityEvent(
353362
};
354363

355364
if (IS_PRODUCTION) {
356-
console.warn(`🚨 Security Event: ${eventType}`, logData);
365+
logger.warn(`🚨 Security Event: ${eventType}`, logData);
357366
} else {
358-
console.log(`🔍 Security Event (disabled): ${eventType}`, {
359-
webhookToken,
360-
ip,
361-
});
367+
logger.info(`🔍 Security Event (disabled): ${eventType}`, logData);
362368
}
363369
}
364370

@@ -379,7 +385,9 @@ function logSecurityEvent(
379385
// })
380386
// .where(eq(userStripeConfig.webhookToken, webhookToken))
381387
// } catch (error) {
382-
// console.error('Error updating webhook success:', error)
388+
// logger.error('Error updating webhook success:', {
389+
// error: error instanceof Error ? error.message : 'Unknown error',
390+
// });
383391
// }
384392
// }
385393

@@ -398,7 +406,9 @@ function logSecurityEvent(
398406
// })
399407
// .where(eq(userStripeConfig.webhookToken, webhookToken))
400408
// } catch (error) {
401-
// console.error('Error updating webhook failure:', error)
409+
// logger.error('Error updating webhook failure:', {
410+
// error: error instanceof Error ? error.message : 'Unknown error',
411+
// });
402412
// }
403413
// }
404414

apps/basket/src/utils/event-schema.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ const resolutionSchema = z
66
.regex(resolutionRegex, "Must be in the format 'WIDTHxHEIGHT'")
77
.refine((val) => {
88
const match = val.match(resolutionRegex);
9-
if (!match) return false;
9+
if (!match) {
10+
return false;
11+
}
1012
const width = Number(match[1]);
1113
const height = Number(match[2]);
1214
return width >= 240 && width <= 10_000 && height >= 240 && height <= 10_000;

apps/basket/src/utils/ip-geo.ts

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ import {
55
BadMethodCallError,
66
Reader,
77
} from '@maxmind/geoip2-node';
8+
import { logger } from '../lib/logger';
89

910
interface GeoIPReader extends Reader {
1011
city(ip: string): City;
1112
}
1213

13-
// Database configuration
1414
const CDN_URL = 'https://cdn.databuddy.cc/GeoLite2-City.mmdb';
1515

1616
let reader: GeoIPReader | null = null;
@@ -30,22 +30,20 @@ async function loadDatabaseFromCdn(): Promise<Buffer> {
3030
const arrayBuffer = await response.arrayBuffer();
3131
const dbBuffer = Buffer.from(arrayBuffer);
3232

33-
// Validate that we got a reasonable file size (should be ~50-100MB)
3433
if (dbBuffer.length < 1_000_000) {
35-
// Less than 1MB
3634
throw new Error(
3735
`Database file seems too small: ${dbBuffer.length} bytes`
3836
);
3937
}
4038

4139
return dbBuffer;
4240
} catch (error) {
43-
console.error('Failed to load database from CDN:', error);
41+
logger.error('Failed to load database from CDN:', { error });
4442
throw error;
4543
}
4644
}
4745

48-
async function loadDatabase() {
46+
function loadDatabase() {
4947
if (loadError) {
5048
throw loadError;
5149
}
@@ -63,12 +61,11 @@ async function loadDatabase() {
6361
try {
6462
const dbBuffer = await loadDatabaseFromCdn();
6563

66-
// Add a small delay to prevent overwhelming the system
6764
await new Promise((resolve) => setTimeout(resolve, 100));
6865

6966
reader = Reader.openBuffer(dbBuffer) as GeoIPReader;
7067
} catch (error) {
71-
console.error('Failed to load GeoIP database:', error);
68+
logger.error('Failed to load GeoIP database:', { error });
7269
loadError = error as Error;
7370
reader = null;
7471
} finally {
@@ -79,21 +76,25 @@ async function loadDatabase() {
7976
return loadPromise;
8077
}
8178

82-
// Don't initialize on module load - wait for first use
8379
const ignore = ['127.0.0.1', '::1'];
8480

85-
// Helper function to validate IP address format
81+
const ipv4Regex =
82+
/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
83+
84+
const ipv6Regex = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
85+
8686
function isValidIp(ip: string): boolean {
87-
if (!ip) return false;
87+
if (!ip) {
88+
return false;
89+
}
8890

89-
// Check for IPv4 format
90-
const ipv4Regex =
91-
/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
92-
if (ipv4Regex.test(ip)) return true;
91+
if (ipv4Regex.test(ip)) {
92+
return true;
93+
}
9394

94-
// Check for IPv6 format (basic check)
95-
const ipv6Regex = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
96-
if (ipv6Regex.test(ip)) return true;
95+
if (ipv6Regex.test(ip)) {
96+
return true;
97+
}
9798

9899
return false;
99100
}
@@ -103,12 +104,11 @@ export async function getGeoLocation(ip: string) {
103104
return { country: undefined, region: undefined, city: undefined };
104105
}
105106

106-
// Lazy load database on first use
107107
if (!(reader || isLoading || loadError)) {
108108
try {
109109
await loadDatabase();
110110
} catch (error) {
111-
console.error('Failed to load database for IP lookup:', error);
111+
logger.error('Failed to load database for IP lookup:', { error });
112112
return { country: undefined, region: undefined, city: undefined };
113113
}
114114
}
@@ -137,41 +137,48 @@ export async function getGeoLocation(ip: string) {
137137

138138
// Handle BadMethodCallError (wrong database type)
139139
if (error instanceof BadMethodCallError) {
140-
console.error(
140+
logger.error(
141141
'Database type mismatch - using city() method with ipinfo database'
142142
);
143143
return { country: undefined, region: undefined, city: undefined };
144144
}
145145

146-
// Handle other errors
147-
console.error('Error looking up IP:', ip, error);
146+
logger.error('Error looking up IP:', { ip, error });
148147
return { country: undefined, region: undefined, city: undefined };
149148
}
150149
}
151150

152151
export function getClientIp(req: Request): string | undefined {
153152
const cfIp = req.headers.get('cf-connecting-ip');
154-
if (cfIp) return cfIp;
153+
if (cfIp) {
154+
return cfIp;
155+
}
155156

156157
const forwardedFor = req.headers.get('x-forwarded-for');
157158
if (forwardedFor) {
158159
const firstIp = forwardedFor.split(',')[0]?.trim();
159-
if (firstIp) return firstIp;
160+
if (firstIp) {
161+
return firstIp;
162+
}
160163
}
161164

162165
const realIp = req.headers.get('x-real-ip');
163-
if (realIp) return realIp;
166+
if (realIp) {
167+
return realIp;
168+
}
164169

165170
return;
166171
}
167172

168-
export async function parseIp(req: Request) {
173+
export function parseIp(req: Request) {
169174
const ip = getClientIp(req);
170175
return getGeoLocation(ip || '');
171176
}
172177

173178
export function anonymizeIp(ip: string): string {
174-
if (!ip) return '';
179+
if (!ip) {
180+
return '';
181+
}
175182

176183
const salt = process.env.IP_HASH_SALT || 'databuddy-ip-salt';
177184
const hash = createHash('sha256');
@@ -191,14 +198,20 @@ export async function getGeo(ip: string) {
191198

192199
export function extractIpFromRequest(request: Request): string {
193200
const cfIp = request.headers.get('cf-connecting-ip');
194-
if (cfIp) return cfIp.trim();
201+
if (cfIp) {
202+
return cfIp.trim();
203+
}
195204

196205
const forwardedFor = request.headers.get('x-forwarded-for');
197206
const firstIp = forwardedFor?.split(',')[0]?.trim();
198-
if (firstIp) return firstIp;
207+
if (firstIp) {
208+
return firstIp;
209+
}
199210

200211
const realIp = request.headers.get('x-real-ip');
201-
if (realIp) return realIp.trim();
212+
if (realIp) {
213+
return realIp.trim();
214+
}
202215

203216
return '';
204217
}

apps/basket/src/utils/user-agent.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* and platform identification.
66
*/
77

8-
import { bots } from '@databuddy/shared';
8+
import { bots, logger } from '@databuddy/shared';
99
import { UAParser } from 'ua-parser-js';
1010

1111
export interface UserAgentInfo {
@@ -57,7 +57,13 @@ export function parseUserAgent(userAgent: string): {
5757
deviceModel: result.device.model || undefined,
5858
};
5959
} catch (error) {
60-
// If parsing fails, return undefined values
60+
logger.error(
61+
'User Agent Parse Error',
62+
`Failed to parse user agent: ${userAgent}`,
63+
{
64+
error: error instanceof Error ? error.message : 'Unknown error',
65+
}
66+
);
6167
return {
6268
browserName: undefined,
6369
browserVersion: undefined,

0 commit comments

Comments
 (0)