-
-
Notifications
You must be signed in to change notification settings - Fork 11
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
add auth #26
add auth #26
Changes from all commits
460d47f
9fa255b
5b4aadf
a275cf5
5c650c8
0d142ce
dc51fe2
b9f9ce2
2dad8a8
d60a381
96e1247
cc32c65
4a7e4d7
207a852
de57e71
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
public-hoist-pattern[]=* |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,46 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { Hono } from "hono"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const app = new Hono(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { prisma } from "@repo/db"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
app | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.get("/", async (c) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const user = await prisma.user.findMany(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return c.json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
user, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+4
to
+10
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. Add error handling and authentication middleware to GET endpoint. The GET endpoint has several issues:
Consider implementing this structure: app
.get("/", async (c) => {
+ try {
+ const page = parseInt(c.req.query('page') ?? '1');
+ const limit = parseInt(c.req.query('limit') ?? '10');
+
const user = await prisma.user.findMany({
+ take: limit,
+ skip: (page - 1) * limit
+ });
return c.json({
- user,
+ data: user,
+ page,
+ limit,
+ success: true
});
+ } catch (error) {
+ return c.json({
+ success: false,
+ error: 'Failed to fetch users'
+ }, 500);
+ }
})
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.patch(async (c) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const name = await c.req.json(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const test = await prisma.user.update({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
where: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
id: "123", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
data: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
name: name.name, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return c.json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
test, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+11
to
+24
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. Critical: Remove hardcoded ID and add proper validation in PATCH endpoint. Several critical issues in the PATCH endpoint:
Apply these changes: - .patch(async (c) => {
+ .patch("/:id", async (c) => {
+ try {
+ const userId = c.req.param('id');
const name = await c.req.json();
+
+ if (!name.name || typeof name.name !== 'string') {
+ return c.json({
+ success: false,
+ error: 'Invalid name provided'
+ }, 400);
+ }
+
const test = await prisma.user.update({
where: {
- id: "123",
+ id: userId,
},
data: {
name: name.name,
},
});
return c.json({
- test,
+ data: test,
+ success: true
});
+ } catch (error) {
+ return c.json({
+ success: false,
+ error: 'Failed to update user'
+ }, 500);
+ }
}) 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.delete(async (c) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const test = await prisma.user.delete({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
where: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
id: "2", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return c.json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
test, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+25
to
+34
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. Critical: Remove hardcoded ID and add proper error handling in DELETE endpoint. The DELETE endpoint has similar issues:
Apply these changes: - .delete(async (c) => {
+ .delete("/:id", async (c) => {
+ try {
+ const userId = c.req.param('id');
const test = await prisma.user.delete({
where: {
- id: "2",
+ id: userId,
},
});
return c.json({
- test,
+ data: test,
+ success: true
});
+ } catch (error) {
+ if (error.code === 'P2025') {
+ return c.json({
+ success: false,
+ error: 'User not found'
+ }, 404);
+ }
+ return c.json({
+ success: false,
+ error: 'Failed to delete user'
+ }, 500);
+ }
}) 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.post(async (c) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const body = await c.req.json(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
console.log(body); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const test = await prisma.user.create({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
data: body, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return c.json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
test, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+35
to
+44
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. Critical: Remove console.log and add input validation in POST endpoint. Issues in the POST endpoint:
Apply these changes: .post(async (c) => {
+ try {
const body = await c.req.json();
- console.log(body);
+
+ // Validate required fields
+ if (!body.email || !body.name) {
+ return c.json({
+ success: false,
+ error: 'Email and name are required'
+ }, 400);
+ }
+
const test = await prisma.user.create({
data: body,
});
return c.json({
- test,
+ data: test,
+ success: true
});
+ } catch (error) {
+ if (error.code === 'P2002') {
+ return c.json({
+ success: false,
+ error: 'User already exists'
+ }, 409);
+ }
+ return c.json({
+ success: false,
+ error: 'Failed to create user'
+ }, 500);
+ }
}) 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export default app; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { Hono } from "hono"; | ||
import { sendBatchEmail, sendEmail } from "@repo/mail"; | ||
import { mailBatchSchema, mailSchema } from "@repo/types"; | ||
import { zValidator } from "@hono/zod-validator"; | ||
|
||
const app = new Hono(); | ||
|
||
app | ||
.post("/send", zValidator("json", mailSchema), async (c) => { | ||
const { email, subject } = c.req.valid("json"); | ||
const { data, error } = await sendEmail(email, subject); | ||
if (error) { | ||
return c.json( | ||
{ | ||
message: "Email sent failed", | ||
}, | ||
400, | ||
); | ||
} | ||
return c.json( | ||
{ | ||
message: "Email sent successfully", | ||
data, | ||
}, | ||
200, | ||
); | ||
}) | ||
.get((c) => { | ||
return c.json({ | ||
message: "mail api is alive", | ||
status: 200, | ||
}); | ||
}); | ||
Comment on lines
+8
to
+33
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. 🛠️ Refactor suggestion Add rate limiting and improve error handling for the email endpoint. While the basic functionality is implemented correctly, consider the following security and observability improvements:
Here's a suggested improvement: app
+ .use("/send", rateLimiter({ max: 10, window: "10m" }))
.post("/send", zValidator("json", mailSchema), async (c) => {
const { email, subject } = c.req.valid("json");
+ const sanitizedSubject = sanitizeHtml(subject);
+ logger.info(`Sending email to ${email}`);
const { data, error } = await sendEmail(email, sanitizedSubject);
if (error) {
+ logger.error(`Email send failed: ${error.message}`);
return c.json(
{
- message: "Email sent failed",
+ message: `Email send failed: ${error.message}`,
},
400,
);
}
+ logger.info(`Email sent successfully to ${email}`);
return c.json(
|
||
|
||
app | ||
.post("/send-batch", zValidator("json", mailBatchSchema), async (c) => { | ||
const { emails, subject } = c.req.valid("json"); | ||
const { data, error } = await sendBatchEmail(emails, subject); | ||
if (error) { | ||
return c.json( | ||
{ | ||
message: "Email sent failed", | ||
}, | ||
400, | ||
); | ||
} | ||
return c.json( | ||
{ | ||
message: "All Emails sent successfully", | ||
data, | ||
}, | ||
200, | ||
); | ||
}) | ||
.get((c) => { | ||
return c.json({ | ||
message: "all mail api is alive", | ||
status: 200, | ||
}); | ||
}); | ||
Comment on lines
+35
to
+60
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. 🛠️ Refactor suggestion Enhance batch email processing with limits and concurrent handling. The batch endpoint needs additional safeguards and optimizations:
Here's a suggested improvement: app
.post("/send-batch", zValidator("json", mailBatchSchema), async (c) => {
const { emails, subject } = c.req.valid("json");
+ if (emails.length > 100) {
+ return c.json({ message: "Batch size exceeds maximum limit of 100" }, 400);
+ }
+ const sanitizedSubject = sanitizeHtml(subject);
+ logger.info(`Processing batch email to ${emails.length} recipients`);
- const { data, error } = await sendBatchEmail(emails, subject);
+ const { data, error } = await Promise.all(
+ emails.map(email => sendEmail(email, sanitizedSubject))
+ );
if (error) {
+ logger.error(`Batch email failed: ${error.message}`);
return c.json(
{
- message: "Email sent failed",
+ message: `Batch email failed: ${error.message}`,
+ failedEmails: error.failed,
},
400,
);
}
|
||
|
||
export default app; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,63 +1,104 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { prisma } from "@repo/db"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { Hono } from "hono"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { handle } from "hono/vercel"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { Hono } from "hono"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { auth } from "@repo/auth"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { cors } from "hono/cors"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import mail from "./mail"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import hello from "./hello"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const allowedOrigins = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"http://localhost:3003", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"https://www.plura.pro", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"http://app.plura.pro", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const runtime = "nodejs"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const app = new Hono().basePath("/api"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const app = new Hono<{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Variables: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
user: typeof auth.$Infer.Session.user | null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
session: typeof auth.$Infer.Session.session | null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}>().basePath("/api"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
app | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.get("/hello", async (c) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const test = await prisma.user.findMany(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return c.json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
test, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.patch(async (c) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const name = await c.req.json(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const test = await prisma.user.update({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
where: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
id: "123", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
data: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
name: name.name, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return c.json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
test, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.delete(async (c) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const test = await prisma.user.delete({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
where: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
id: "2", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
app.use( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"/auth/**", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cors({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
origin: allowedOrigins, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
allowHeaders: ["Content-Type", "Authorization"], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
allowMethods: ["POST", "GET", "OPTIONS"], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
exposeHeaders: ["Content-Length"], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
maxAge: 600, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
credentials: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
app.options("/auth/**", (c) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const origin = c.req.raw.headers.get("origin") ?? ""; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (allowedOrigins.includes(origin)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return new Response(null, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
status: 204, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
headers: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Access-Control-Allow-Origin": origin, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Access-Control-Allow-Methods": "GET, POST, OPTIONS", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Access-Control-Allow-Headers": "Content-Type, Authorization", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Access-Control-Allow-Credentials": "true", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Access-Control-Max-Age": "600", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return c.json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
test, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.post(async (c) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const body = await c.req.json(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
console.log(body); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const test = await prisma.user.create({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
data: body, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return c.json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
test, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return new Response("Forbidden", { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
status: 403, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
app.use("*", async (c, next) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const session = await auth.api.getSession({ headers: c.req.raw.headers }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!session) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
c.set("user", null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
c.set("session", null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return next(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
c.set("user", session.user); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
c.set("session", session.session); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return next(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+55
to
+67
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. 🛠️ Refactor suggestion Add error handling for The middleware currently does not handle potential errors from Apply this diff to add error handling: app.use("*", async (c, next) => {
+ try {
const session = await auth.api.getSession({ headers: c.req.raw.headers });
if (!session) {
c.set("user", null);
c.set("session", null);
return next();
}
c.set("user", session.user);
c.set("session", session.session);
return next();
+ } catch (error) {
+ c.set("user", null);
+ c.set("session", null);
+ return next();
+ }
}); 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
app.get("/health", async (c) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return c.json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
message: "i am alive", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
status: 200, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
app.get("/session", async (c) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const session = c.get("session"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const user = c.get("user"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!user) return c.body(null, 401); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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. 🛠️ Refactor suggestion Correct response method for unauthorized access. The method - if (!user) return c.body(null, 401);
+ if (!user) return c.text('Unauthorized', 401); 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return c.json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
session, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
user, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
app.route("/hello", hello); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
app.route("/mail", mail); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
app.on(["POST", "GET"], "/auth/**", (c) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return auth.handler(c.req.raw); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
app.get("/multi-sessions", async (c) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const res = await auth.api.listDeviceSessions({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
headers: c.req.raw.headers, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return c.json(res); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const GET = handle(app); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const POST = handle(app); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const PATCH = handle(app); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const DELETE = handle(app); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const OPTIONS = handle(app); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export { GET, PATCH, POST, DELETE }; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,14 @@ | ||||||||||||||||||||||||||||||||||||||||||
import AccountSwitcher from "@/components/custom/account-switcher"; | ||||||||||||||||||||||||||||||||||||||||||
import { getMultipleSessions, getSession } from "@/lib/server"; | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
export default async function page() { | ||||||||||||||||||||||||||||||||||||||||||
const session = await getSession(); | ||||||||||||||||||||||||||||||||||||||||||
const multipleSessions = await getMultipleSessions(); | ||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+4
to
+7
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. Add error handling for API calls. The component makes two API calls without any error handling. Failed API calls could crash the entire page. export default async function page() {
- const session = await getSession();
- const multipleSessions = await getMultipleSessions();
+ try {
+ const [session, multipleSessions] = await Promise.all([
+ getSession(),
+ getMultipleSessions(),
+ ]);
+ return (
+ <div>
+ <AccountSwitcher session={multipleSessions} activeSession={session} />
+ <pre className="font-sm">{JSON.stringify(session, null, 1)}</pre>
+ </div>
+ );
+ } catch (error) {
+ console.error('Failed to fetch session data:', error);
+ return <div>Failed to load dashboard. Please try again later.</div>;
+ } 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
<div> | ||||||||||||||||||||||||||||||||||||||||||
<AccountSwitcher session={multipleSessions} activeSession={session} /> | ||||||||||||||||||||||||||||||||||||||||||
<pre className="font-sm">{JSON.stringify(session, null, 1)}</pre> | ||||||||||||||||||||||||||||||||||||||||||
{/* <pre>{JSON.stringify(multipleSessions,null,2)}</pre> */} | ||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+10
to
+11
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. Security concern: Avoid displaying raw session data. Displaying raw session data in the UI could expose sensitive information. Consider showing only necessary user information. - <pre className="font-sm">{JSON.stringify(session, null, 1)}</pre>
+ {session?.user && (
+ <div className="text-sm">
+ Logged in as: {session.user.email}
+ </div>
+ )} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,10 @@ | ||||||
import SignIn from "@/components/custom/Sign-In"; | ||||||
|
||||||
export default function page() { | ||||||
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. 🛠️ Refactor suggestion Rename component to follow React naming convention. React components should use PascalCase naming. Rename -export default function page() {
+export default function SignInPage() { 📝 Committable suggestion
Suggested change
|
||||||
return ( | ||||||
<div className="w-full h-screen flex items-center justify-center"> | ||||||
{" "} | ||||||
<SignIn /> | ||||||
</div> | ||||||
); | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import SignUp from "../../../components/custom/Sign-up"; | ||
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. 🛠️ Refactor suggestion Fix import path and component naming inconsistency. The import statement has two issues:
Consider these improvements: -import SignUp from "../../../components/custom/Sign-up";
+import { SignUp } from "@/components/auth/SignUp"; Also, rename the component file from
|
||
|
||
export default function page() { | ||
return ( | ||
<div className="w-full h-screen flex items-center justify-center"> | ||
<SignUp /> | ||
</div> | ||
); | ||
} |
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.
💡 Codebase verification
Request validation is already supported but not implemented
The project already has
@hono/zod-validator
andzod
dependencies installed, and there's an existing pattern of request validation inmail.ts
usingzValidator
middleware. You should implement similar validation for your endpoints using the existing setup:zValidator
from@hono/zod-validator
@repo/types
zValidator
middleware to your routesExample from
mail.ts
:🔗 Analysis chain
Consider adding request validation middleware.
Since this is an authentication-related PR, it's crucial to validate incoming requests. Consider adding middleware like
zod
for request validation.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 57
Script:
Length of output: 618
Script:
Length of output: 2648