Skip to content

Commit 5e98272

Browse files
committed
cleaner utils in api
1 parent adfaeb7 commit 5e98272

File tree

2 files changed

+59
-5
lines changed

2 files changed

+59
-5
lines changed

apps/api/src/middleware/website-auth.ts

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { auth } from "@databuddy/auth";
2+
import { and, db, eq, member } from "@databuddy/db";
23
import { Elysia } from "elysia";
34
import {
45
getApiKeyFromHeader,
@@ -95,7 +96,7 @@ function checkNoWebsiteAuth(
9596

9697
async function checkWebsiteAuth(
9798
websiteId: string,
98-
sessionUser: unknown,
99+
sessionUser: { id: string; name: string; email: string } | unknown,
99100
apiKey: Parameters<typeof hasWebsiteScope>[0] | null,
100101
apiKeyPresent: boolean
101102
): Promise<Response | null> {
@@ -110,9 +111,42 @@ async function checkWebsiteAuth(
110111
if (website.isPublic) {
111112
return null;
112113
}
113-
if (sessionUser) {
114-
return null;
114+
115+
// Check session-based authentication
116+
if (sessionUser && typeof sessionUser === "object" && "id" in sessionUser) {
117+
const userId = (sessionUser as { id: string }).id;
118+
119+
// Check if user owns the website directly (personal website)
120+
if (website.userId === userId && !website.organizationId) {
121+
return null;
122+
}
123+
124+
// Check if user has access through organization membership
125+
if (website.organizationId) {
126+
const membership = await db.query.member.findFirst({
127+
where: and(
128+
eq(member.userId, userId),
129+
eq(member.organizationId, website.organizationId)
130+
),
131+
columns: {
132+
id: true,
133+
},
134+
});
135+
136+
if (membership) {
137+
return null;
138+
}
139+
}
140+
141+
// User is authenticated but doesn't have access to this website
142+
return json(403, {
143+
success: false,
144+
error: "Access denied to this website",
145+
code: "FORBIDDEN",
146+
});
115147
}
148+
149+
// No session user, check API key
116150
if (!apiKeyPresent) {
117151
return json(401, {
118152
success: false,

apps/api/src/routes/query.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { auth } from "@databuddy/auth";
2-
import { and, db, eq, inArray, isNull, websites } from "@databuddy/db";
2+
import { and, db, eq, inArray, isNull, member, websites } from "@databuddy/db";
33
import { filterOptions } from "@databuddy/shared/lists/filters";
44
import { Elysia, t } from "elysia";
55
import {
@@ -136,7 +136,27 @@ async function verifyWebsiteAccess(
136136
}
137137

138138
if (ctx.user) {
139-
return website.userId === ctx.user.id && !website.organizationId;
139+
// Direct ownership (personal websites)
140+
if (website.userId === ctx.user.id && !website.organizationId) {
141+
return true;
142+
}
143+
144+
// Organization access - check if user is a member of the website's organization
145+
if (website.organizationId) {
146+
const membership = await db.query.member.findFirst({
147+
where: and(
148+
eq(member.userId, ctx.user.id),
149+
eq(member.organizationId, website.organizationId)
150+
),
151+
columns: {
152+
id: true,
153+
},
154+
});
155+
156+
return !!membership;
157+
}
158+
159+
return false;
140160
}
141161

142162
return false;

0 commit comments

Comments
 (0)