forked from vercel/platforms
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathauth.ts
139 lines (129 loc) · 3.38 KB
/
auth.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import { getServerSession, type NextAuthOptions } from "next-auth";
import GitHubProvider from "next-auth/providers/github";
import db from "./db";
import { DrizzleAdapter } from "@auth/drizzle-adapter";
import { Adapter } from "next-auth/adapters";
import { accounts, sessions, users, verificationTokens } from "./schema";
const VERCEL_DEPLOYMENT = !!process.env.VERCEL_URL;
export const authOptions: NextAuthOptions = {
providers: [
GitHubProvider({
clientId: process.env.AUTH_GITHUB_ID as string,
clientSecret: process.env.AUTH_GITHUB_SECRET as string,
profile(profile) {
return {
id: profile.id.toString(),
name: profile.name || profile.login,
gh_username: profile.login,
email: profile.email,
image: profile.avatar_url,
};
},
}),
],
pages: {
signIn: `/login`,
verifyRequest: `/login`,
error: "/login", // Error code passed in query string as ?error=
},
adapter: DrizzleAdapter(db, {
usersTable: users,
accountsTable: accounts,
sessionsTable: sessions,
verificationTokensTable: verificationTokens,
}) as Adapter,
session: { strategy: "jwt" },
cookies: {
sessionToken: {
name: `${VERCEL_DEPLOYMENT ? "__Secure-" : ""}next-auth.session-token`,
options: {
httpOnly: true,
sameSite: "lax",
path: "/",
// When working on localhost, the cookie domain must be omitted entirely (https://stackoverflow.com/a/1188145)
domain: VERCEL_DEPLOYMENT
? `.${process.env.NEXT_PUBLIC_ROOT_DOMAIN}`
: undefined,
secure: VERCEL_DEPLOYMENT,
},
},
},
callbacks: {
jwt: async ({ token, user }) => {
if (user) {
token.user = user;
}
return token;
},
session: async ({ session, token }) => {
session.user = {
...session.user,
// @ts-expect-error
id: token.sub,
// @ts-expect-error
username: token?.user?.username || token?.user?.gh_username,
};
return session;
},
},
};
export function getSession() {
return getServerSession(authOptions) as Promise<{
user: {
id: string;
name: string;
username: string;
email: string;
image: string;
};
} | null>;
}
export function withSiteAuth(action: any) {
return async (
formData: FormData | null,
siteId: string,
key: string | null,
) => {
const session = await getSession();
if (!session) {
return {
error: "Not authenticated",
};
}
const site = await db.query.sites.findFirst({
where: (sites, { eq }) => eq(sites.id, siteId),
});
if (!site || site.userId !== session.user.id) {
return {
error: "Not authorized",
};
}
return action(formData, site, key);
};
}
export function withPostAuth(action: any) {
return async (
formData: FormData | null,
postId: string,
key: string | null,
) => {
const session = await getSession();
if (!session?.user.id) {
return {
error: "Not authenticated",
};
}
const post = await db.query.posts.findFirst({
where: (posts, { eq }) => eq(posts.id, postId),
with: {
site: true,
},
});
if (!post || post.userId !== session.user.id) {
return {
error: "Post not found",
};
}
return action(formData, post, key);
};
}