Skip to content

Commit 619d8b3

Browse files
committed
feat: add access control to project
1 parent 51ce76f commit 619d8b3

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { api } from "@/trpc/server";
2+
import { Routes } from "@/utils/constants";
3+
import { Icons } from "@onlook/ui/icons/index";
4+
import Link from "next/link";
5+
6+
export default async function Layout({ params, children }: Readonly<{ params: Promise<{ id: string }>, children: React.ReactNode }>) {
7+
const projectId = (await params).id;
8+
const hasAccess = await api.project.hasAccess({ projectId });
9+
if (!hasAccess) {
10+
return <NoAccess />;
11+
}
12+
return <>{children}</>;
13+
}
14+
15+
const NoAccess = () => {
16+
const SUPPORT_EMAIL = '[email protected]';
17+
return (
18+
<main className="flex flex-1 flex-col items-center justify-center h-screen w-screen p-4 text-center">
19+
<div className="space-y-6">
20+
<div className="space-y-2">
21+
<h1 className="text-4xl font-bold tracking-tight text-foreground-primary">Access denied</h1>
22+
<h2 className="text-2xl font-semibold tracking-tight text-foreground-primary">{`Please contact the project owner to request access.`}</h2>
23+
<p className="text-foreground-secondary">
24+
{`Please email `}
25+
<Link href={`mailto:${SUPPORT_EMAIL}`} className="text-primary underline">
26+
{SUPPORT_EMAIL}
27+
</Link>
28+
{` if you believe this is an error.`}
29+
</p>
30+
</div>
31+
32+
<Link
33+
className="inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm hover:bg-primary/90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary"
34+
href={Routes.PROJECTS}
35+
>
36+
<Icons.ArrowLeft className="h-4 w-4" />
37+
Back to projects
38+
</Link>
39+
</div>
40+
</main>
41+
);
42+
};

apps/web/client/src/server/api/routers/project/project.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@ import { createTRPCRouter, protectedProcedure } from '../../trpc';
3333
import { projectCreateRequestRouter } from './createRequest';
3434

3535
export const projectRouter = createTRPCRouter({
36+
hasAccess: protectedProcedure
37+
.input(z.object({ projectId: z.string() }))
38+
.query(async ({ ctx, input }) => {
39+
const user = ctx.user;
40+
const project = await ctx.db.query.projects.findFirst({
41+
where: eq(projects.id, input.projectId),
42+
with: {
43+
userProjects: {
44+
where: eq(userProjects.userId, user.id),
45+
},
46+
},
47+
});
48+
return !!project && project.userProjects.length > 0;
49+
}),
3650
createRequest: projectCreateRequestRouter,
3751
captureScreenshot: protectedProcedure
3852
.input(z.object({ projectId: z.string() }))

0 commit comments

Comments
 (0)