-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
✨ feat: add base pages and auth #14
Changes from 2 commits
246f8c3
6a20c95
15e36f6
bd9ced4
270def9
8f8ed35
1488404
ee3e246
ec1026a
865c884
f95e590
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2,76 +2,89 @@ import { OAuth2RequestError } from "arctic"; | |||||||||||||||
import { DatabaseUser, generateIdFromEntropySize } from "lucia"; | ||||||||||||||||
import clientPromise from "~/server/utils/mongodb"; | ||||||||||||||||
import { github } from "~/server/utils/auth"; | ||||||||||||||||
import mongoose from "mongoose"; | ||||||||||||||||
|
||||||||||||||||
export default defineEventHandler(async (event) => { | ||||||||||||||||
const client = await clientPromise; | ||||||||||||||||
await client.connect(); | ||||||||||||||||
const client = await clientPromise; | ||||||||||||||||
await client.connect(); | ||||||||||||||||
|
||||||||||||||||
const db = client.db(); | ||||||||||||||||
const query = getQuery(event); | ||||||||||||||||
const code = query.code?.toString() ?? null; | ||||||||||||||||
const state = query.state?.toString() ?? null; | ||||||||||||||||
const storedState = getCookie(event, "github_oauth_state") ?? null; | ||||||||||||||||
if (!code || !state || !storedState || state !== storedState) { | ||||||||||||||||
throw createError({ | ||||||||||||||||
status: 400 | ||||||||||||||||
}); | ||||||||||||||||
} | ||||||||||||||||
const db = client.db(); | ||||||||||||||||
const query = getQuery(event); | ||||||||||||||||
const code = query.code?.toString() ?? null; | ||||||||||||||||
const state = query.state?.toString() ?? null; | ||||||||||||||||
const storedState = getCookie(event, "github_oauth_state") ?? null; | ||||||||||||||||
if (!code || !state || !storedState || state !== storedState) { | ||||||||||||||||
throw createError({ | ||||||||||||||||
status: 400, | ||||||||||||||||
}); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
try { | ||||||||||||||||
const tokens = await github.validateAuthorizationCode(code); | ||||||||||||||||
try { | ||||||||||||||||
const tokens = await github.validateAuthorizationCode(code); | ||||||||||||||||
|
||||||||||||||||
const githubUserResponse = await fetch("https://api.github.com/user", { | ||||||||||||||||
headers: { | ||||||||||||||||
Authorization: `Bearer ${tokens.accessToken}` | ||||||||||||||||
} | ||||||||||||||||
}); | ||||||||||||||||
const githubUser: GitHubUser = await githubUserResponse.json(); | ||||||||||||||||
const githubUserResponse = await fetch("https://api.github.com/user", { | ||||||||||||||||
headers: { | ||||||||||||||||
Authorization: `Bearer ${tokens.accessToken}`, | ||||||||||||||||
}, | ||||||||||||||||
}); | ||||||||||||||||
const githubUser: GitHubUser = await githubUserResponse.json(); | ||||||||||||||||
|
||||||||||||||||
// Replace this with your own DB client. | ||||||||||||||||
const existingUser = await db.collection("user").findOne({ github_id: githubUser.id }); | ||||||||||||||||
// Replace this with your own DB client. | ||||||||||||||||
const existingUser = await db | ||||||||||||||||
.collection("users") | ||||||||||||||||
.findOne({ github_id: githubUser.id }); | ||||||||||||||||
|
||||||||||||||||
// console.log("EXISTING USER: " + JSON.stringify(existingUser)) | ||||||||||||||||
// const { _id } = existingUser; | ||||||||||||||||
// console.log("EXISTING USER ID: " + _id) | ||||||||||||||||
if (existingUser) { | ||||||||||||||||
const session = await lucia.createSession(existingUser._id, {}); | ||||||||||||||||
// Update the session in the DB | ||||||||||||||||
// Replace this with your own DB client. | ||||||||||||||||
// await db.collection("session").updateOne({ _id: session.id }, { $set: { _id: _id } }); | ||||||||||||||||
// console.log("SESSION: " + JSON.stringify(session)); | ||||||||||||||||
appendHeader(event, "Set-Cookie", lucia.createSessionCookie(session.id).serialize()); | ||||||||||||||||
return sendRedirect(event, "/profile"); | ||||||||||||||||
} | ||||||||||||||||
// console.log("EXISTING USER: " + JSON.stringify(existingUser)) | ||||||||||||||||
// console.log("EXISTING USER ID: " + _id) | ||||||||||||||||
if (existingUser) { | ||||||||||||||||
const { _id } = existingUser; | ||||||||||||||||
const session = await lucia.createSession(existingUser._id, {}); | ||||||||||||||||
// Update the session in the DB | ||||||||||||||||
// Replace this with your own DB client. | ||||||||||||||||
await db | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (code_refinement): Consider the implications of direct database manipulations within route handlers. Directly manipulating the database within route handlers can lead to tightly coupled code that is harder to maintain. Consider abstracting database interactions to a separate layer or service.
Suggested change
|
||||||||||||||||
.collection("session") | ||||||||||||||||
.updateOne({ _id: session.id }, { $set: { _id: _id } }); | ||||||||||||||||
// console.log("SESSION: " + JSON.stringify(session)); | ||||||||||||||||
appendHeader( | ||||||||||||||||
event, | ||||||||||||||||
"Set-Cookie", | ||||||||||||||||
lucia.createSessionCookie(session.id).serialize(), | ||||||||||||||||
); | ||||||||||||||||
return sendRedirect(event, "/profile"); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
const userId = generateIdFromEntropySize(10); // 16 characters long | ||||||||||||||||
const userId = generateIdFromEntropySize(10); // 16 characters long | ||||||||||||||||
|
||||||||||||||||
// Replace this with your own DB client. | ||||||||||||||||
await db.collection("user").insertOne({ | ||||||||||||||||
_id: userId, | ||||||||||||||||
github_id: githubUser.id, | ||||||||||||||||
username: githubUser.login | ||||||||||||||||
}); | ||||||||||||||||
// Replace this with your own DB client. | ||||||||||||||||
await db.collection("users").insertOne({ | ||||||||||||||||
_id: userId, | ||||||||||||||||
github_id: githubUser.id, | ||||||||||||||||
username: githubUser.login, | ||||||||||||||||
}); | ||||||||||||||||
|
||||||||||||||||
const session = await lucia.createSession(userId, {}); | ||||||||||||||||
appendHeader(event, "Set-Cookie", lucia.createSessionCookie(session.id).serialize()); | ||||||||||||||||
return sendRedirect(event, "/profile"); | ||||||||||||||||
} catch (e) { | ||||||||||||||||
// the specific error message depends on the provider | ||||||||||||||||
if (e instanceof OAuth2RequestError) { | ||||||||||||||||
// invalid code | ||||||||||||||||
throw createError({ | ||||||||||||||||
status: 400 | ||||||||||||||||
}); | ||||||||||||||||
} | ||||||||||||||||
throw createError({ | ||||||||||||||||
status: 500, | ||||||||||||||||
}); | ||||||||||||||||
} | ||||||||||||||||
const session = await lucia.createSession(userId, {}); | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (testing): No tests for session creation failure scenarios. It's important to test how the system behaves if session creation fails. This could involve mocking the session creation to throw an error and asserting the error handling in the application.
Suggested change
|
||||||||||||||||
appendHeader( | ||||||||||||||||
event, | ||||||||||||||||
"Set-Cookie", | ||||||||||||||||
lucia.createSessionCookie(session.id).serialize(), | ||||||||||||||||
); | ||||||||||||||||
return sendRedirect(event, "/profile"); | ||||||||||||||||
} catch (e) { | ||||||||||||||||
// the specific error message depends on the provider | ||||||||||||||||
if (e instanceof OAuth2RequestError) { | ||||||||||||||||
// invalid code | ||||||||||||||||
throw createError({ | ||||||||||||||||
status: 400, | ||||||||||||||||
}); | ||||||||||||||||
} | ||||||||||||||||
throw createError({ | ||||||||||||||||
status: 500, | ||||||||||||||||
message: e.message, | ||||||||||||||||
}); | ||||||||||||||||
} | ||||||||||||||||
}); | ||||||||||||||||
|
||||||||||||||||
interface GitHubUser { | ||||||||||||||||
id: string; | ||||||||||||||||
login: string; | ||||||||||||||||
id: string; | ||||||||||||||||
login: string; | ||||||||||||||||
} | ||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (testing): Test coverage needed for mongoose usage in GitHub callback.
Ensure there are tests that cover the integration of mongoose in the GitHub callback logic, particularly how it interacts with the database operations.