Skip to content

Commit 717ee13

Browse files
committed
fix: flags route
1 parent f88b322 commit 717ee13

File tree

4 files changed

+165
-137
lines changed

4 files changed

+165
-137
lines changed

apps/api/src/index.ts

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@ import { query } from "./routes/query";
1717
const rpcHandler = new RPCHandler(appRouter, {
1818
interceptors: [
1919
onError((error) => {
20-
logger.error({
21-
message: error instanceof Error ? error.message : String(error),
22-
error,
23-
});
20+
logger.error(
21+
error
22+
);
2423
}),
2524
],
2625
});
@@ -42,17 +41,28 @@ const app = new Elysia()
4241
.use(
4342
autumnHandler({
4443
identify: async ({ request }) => {
45-
const session = await auth.api.getSession({
46-
headers: request.headers,
47-
});
44+
try {
45+
const session = await auth.api.getSession({
46+
headers: request.headers,
47+
});
4848

49-
return {
50-
customerId: session?.user.id,
51-
customerData: {
52-
name: session?.user.name,
53-
email: session?.user.email,
54-
},
55-
};
49+
return {
50+
customerId: session?.user.id,
51+
customerData: {
52+
name: session?.user.name,
53+
email: session?.user.email,
54+
},
55+
};
56+
} catch (error) {
57+
logger.error({ error }, "Failed to get session for autumn handler");
58+
return {
59+
customerId: null,
60+
customerData: {
61+
name: null,
62+
email: null,
63+
},
64+
};
65+
}
5666
},
5767
})
5868
)
@@ -62,20 +72,25 @@ const app = new Elysia()
6272
.all(
6373
"/rpc/*",
6474
async ({ request }: { request: Request }) => {
65-
const context = await createRPCContext({ headers: request.headers });
66-
const { response } = await rpcHandler.handle(request, {
67-
prefix: "/rpc",
68-
context,
69-
});
70-
return response ?? new Response("Not Found", { status: 404 });
75+
try {
76+
const context = await createRPCContext({ headers: request.headers });
77+
const { response } = await rpcHandler.handle(request, {
78+
prefix: "/rpc",
79+
context,
80+
});
81+
return response ?? new Response("Not Found", { status: 404 });
82+
} catch (error) {
83+
logger.error({ error }, "RPC handler failed");
84+
return new Response("Internal Server Error", { status: 500 });
85+
}
7186
},
7287
{
7388
parse: "none",
7489
}
7590
)
7691
.onError(({ error, code }) => {
7792
const errorMessage = error instanceof Error ? error.message : String(error);
78-
logger.error({ message: errorMessage, code, error });
93+
logger.error({ error, code }, errorMessage);
7994

8095
return new Response(
8196
JSON.stringify({

apps/api/src/routes/export.ts

Lines changed: 86 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const getWebsiteById = cacheable(
2121
where: eq(websites.id, id),
2222
});
2323
} catch (error) {
24-
console.error("Error fetching website by ID:", error, { id });
24+
logger.error({ error, websiteId: id }, "Error fetching website by ID");
2525
return null;
2626
}
2727
},
@@ -41,42 +41,47 @@ async function authorizeWebsiteAccess(
4141
websiteId: string,
4242
permission: "read" | "update" | "delete" | "transfer"
4343
) {
44-
const website = await getWebsiteById(websiteId);
44+
try {
45+
const website = await getWebsiteById(websiteId);
4546

46-
if (!website) {
47-
throw new Error("Website not found");
48-
}
47+
if (!website) {
48+
throw new Error("Website not found");
49+
}
4950

50-
// Public websites allow read access
51-
if (permission === "read" && website.isPublic) {
52-
return website;
53-
}
51+
// Public websites allow read access
52+
if (permission === "read" && website.isPublic) {
53+
return website;
54+
}
5455

55-
const session = await auth.api.getSession({ headers });
56-
const user = session?.user;
56+
const session = await auth.api.getSession({ headers });
57+
const user = session?.user;
5758

58-
if (!user) {
59-
throw new Error("Authentication is required for this action");
60-
}
59+
if (!user) {
60+
throw new Error("Authentication is required for this action");
61+
}
6162

62-
if (user.role === "ADMIN") {
63-
return website;
64-
}
63+
if (user.role === "ADMIN") {
64+
return website;
65+
}
6566

66-
if (website.organizationId) {
67-
const { success } = await websitesApi.hasPermission({
68-
headers,
69-
body: { permissions: { website: [permission] } },
70-
});
71-
if (!success) {
72-
throw new Error("You do not have permission to perform this action");
67+
if (website.organizationId) {
68+
const { success } = await websitesApi.hasPermission({
69+
headers,
70+
body: { permissions: { website: [permission] } },
71+
});
72+
if (!success) {
73+
throw new Error("You do not have permission to perform this action");
74+
}
75+
} else if (website.userId !== user.id) {
76+
// Check direct ownership
77+
throw new Error("You are not the owner of this website");
7378
}
74-
} else if (website.userId !== user.id) {
75-
// Check direct ownership
76-
throw new Error("You are not the owner of this website");
77-
}
7879

79-
return website;
80+
return website;
81+
} catch (error) {
82+
logger.error({ error, websiteId, permission }, "Failed to authorize website access");
83+
throw error;
84+
}
8085
}
8186

8287
export const exportRoute = new Elysia({ prefix: "/v1/export" })
@@ -117,45 +122,46 @@ export const exportRoute = new Elysia({ prefix: "/v1/export" })
117122
);
118123

119124
if (dateError) {
120-
logger.warn({
121-
message: "Export request with invalid dates",
122-
requestId,
123-
websiteId,
124-
startDate: body.start_date,
125-
endDate: body.end_date,
126-
error: dateError,
127-
});
125+
logger.warn(
126+
{
127+
requestId,
128+
websiteId,
129+
startDate: body.start_date,
130+
endDate: body.end_date,
131+
error: dateError,
132+
},
133+
"Export request with invalid dates"
134+
);
128135
return createErrorResponse(400, "INVALID_DATE_RANGE", dateError);
129136
}
130137

131138
const format = body.format || "json";
132139
if (!["csv", "json", "txt", "proto"].includes(format)) {
133-
logger.warn({
134-
message: "Export request with invalid format",
135-
requestId,
136-
websiteId,
137-
format,
138-
});
140+
logger.warn(
141+
{ requestId, websiteId, format },
142+
"Export request with invalid format"
143+
);
139144
return createErrorResponse(
140145
400,
141146
"INVALID_FORMAT",
142147
"Invalid export format. Supported formats: csv, json, txt, proto"
143148
);
144149
}
145150

146-
logger.info({
147-
message: "Data export initiated",
148-
requestId,
149-
websiteId,
150-
startDate: validatedDates.startDate,
151-
endDate: validatedDates.endDate,
152-
format,
153-
userAgent: request.headers.get("user-agent"),
154-
ip:
155-
request.headers.get("x-forwarded-for") ||
156-
request.headers.get("x-real-ip"),
157-
timestamp: new Date().toISOString(),
158-
});
151+
logger.info(
152+
{
153+
requestId,
154+
websiteId,
155+
startDate: validatedDates.startDate,
156+
endDate: validatedDates.endDate,
157+
format,
158+
userAgent: request.headers.get("user-agent"),
159+
ip:
160+
request.headers.get("x-forwarded-for") ||
161+
request.headers.get("x-real-ip"),
162+
},
163+
"Data export initiated"
164+
);
159165

160166
const exportRequest: ExportRequest = {
161167
website_id: websiteId,
@@ -166,16 +172,17 @@ export const exportRoute = new Elysia({ prefix: "/v1/export" })
166172

167173
const result = await processExport(exportRequest);
168174

169-
logger.info({
170-
message: "Data export completed successfully",
171-
requestId,
172-
websiteId,
173-
filename: result.filename,
174-
fileSize: result.buffer.length,
175-
totalRecords: result.metadata.totalRecords,
176-
processingTime: Date.now() - startTime,
177-
timestamp: new Date().toISOString(),
178-
});
175+
logger.info(
176+
{
177+
requestId,
178+
websiteId,
179+
filename: result.filename,
180+
fileSize: result.buffer.length,
181+
totalRecords: result.metadata.totalRecords,
182+
processingTime: Date.now() - startTime,
183+
},
184+
"Data export completed successfully"
185+
);
179186

180187
return new Response(result.buffer, {
181188
headers: {
@@ -185,19 +192,19 @@ export const exportRoute = new Elysia({ prefix: "/v1/export" })
185192
},
186193
});
187194
} catch (error) {
188-
logger.error({
189-
message: "Data export failed",
190-
requestId,
191-
websiteId: body.website_id,
192-
error: error instanceof Error ? error.message : String(error),
193-
stack: error instanceof Error ? error.stack : undefined,
194-
processingTime: Date.now() - startTime,
195-
userAgent: request.headers.get("user-agent"),
196-
ip:
197-
request.headers.get("x-forwarded-for") ||
198-
request.headers.get("x-real-ip"),
199-
timestamp: new Date().toISOString(),
200-
});
195+
logger.error(
196+
{
197+
error,
198+
requestId,
199+
websiteId: body.website_id,
200+
processingTime: Date.now() - startTime,
201+
userAgent: request.headers.get("user-agent"),
202+
ip:
203+
request.headers.get("x-forwarded-for") ||
204+
request.headers.get("x-real-ip"),
205+
},
206+
"Data export failed"
207+
);
201208

202209
if (error instanceof Error) {
203210
if (error.message.includes("not found")) {

apps/api/src/routes/health.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const checkClickhouse = async () => {
88
const result = await chQuery("SELECT 1 FROM analytics.events LIMIT 1");
99
return result.length > 0;
1010
} catch (error) {
11-
logger.error("ClickHouse health check failed:", { error });
11+
logger.error({ error }, "ClickHouse health check failed");
1212
return false;
1313
}
1414
};
@@ -20,7 +20,7 @@ const checkDatabase = async () => {
2020
});
2121
return result.length > 0;
2222
} catch (error) {
23-
logger.error("Database health check failed:", { error });
23+
logger.error({ error }, "Database health check failed");
2424
return false;
2525
}
2626
};
@@ -30,7 +30,7 @@ const checkRedis = async () => {
3030
const result = await redisClient.ping();
3131
return result === "PONG";
3232
} catch (error) {
33-
logger.error("Redis health check failed:", { error });
33+
logger.error({ error }, "Redis health check failed");
3434
return false;
3535
}
3636
};

0 commit comments

Comments
 (0)