Skip to content

Commit a92e365

Browse files
authored
Merge pull request #48 from Nandgopal-R/feat/unauthorized-user
fix: tests
2 parents ba96418 + f414f89 commit a92e365

7 files changed

Lines changed: 52 additions & 14 deletions

File tree

bun.lock

Lines changed: 5 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"@types/pdfkit": "^0.17.5",
2222
"better-auth": "^1.5.4",
2323
"elysia": "^1.4.27",
24+
"file-type": "^21.3.1",
2425
"nodemailer": "^8.0.2",
2526
"pdfkit": "^0.17.2",
2627
"pg": "^8.20.0",
@@ -46,9 +47,10 @@
4647
]
4748
},
4849
"resolutions": {
49-
"hono": "^4.11.10",
50+
"hono": "^4.12.7",
5051
"@hono/node-server": "^1.19.10",
51-
"lodash": "^4.17.23"
52+
"lodash": "^4.17.23",
53+
"file-type": "^21.3.1"
5254
},
5355
"module": "src/index.ts"
5456
}

src/api/auth/requireAuth.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,11 @@ export const requireAuth = (app: Elysia) =>
1818
user: session.user as User,
1919
};
2020
});
21+
22+
export const optionalAuth = (app: Elysia) =>
23+
app.derive(async (context) => {
24+
const session = await auth.api.getSession(context.request);
25+
return {
26+
user: (session?.user as User) ?? null,
27+
};
28+
});

src/api/form-response/controller.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,13 @@ export async function submitResponse({
4040
const response = await prisma.formResponse.create({
4141
data: {
4242
formId: params.formId,
43-
respondentId: user.id,
43+
respondentId: user?.id ?? null,
4444
answers: body.answers,
4545
isSubmitted: body.isSubmitted ?? false,
4646
},
4747
});
4848
logger.info(
49-
`User ${user.id} ${body.isSubmitted ? "submitted" : "saved draft"} response ${response.id} for form ${params.formId}`,
49+
`User ${user?.id ?? "anonymous"} ${body.isSubmitted ? "submitted" : "saved draft"} response ${response.id} for form ${params.formId}`,
5050
);
5151
return {
5252
success: true,

src/api/form-response/routes.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
getSubmittedResponseDTO,
66
resumeResponseDTO,
77
} from "../../types/form-response";
8-
import { requireAuth } from "../auth/requireAuth";
8+
import { optionalAuth, requireAuth } from "../auth/requireAuth";
99
import {
1010
getAllReceivedResponses,
1111
getAllUserResponses,
@@ -15,12 +15,19 @@ import {
1515
submitResponse,
1616
} from "./controller";
1717

18-
export const formResponseRoutes = new Elysia({ prefix: "/responses" })
19-
.use(requireAuth)
18+
const publicResponseRoutes = new Elysia()
19+
.use(optionalAuth)
2020
.post("/submit/:formId", submitResponse, formResponseDTO)
21-
.post("/draft/:formId", submitResponse, formResponseDTO)
21+
.post("/draft/:formId", submitResponse, formResponseDTO);
22+
23+
const protectedResponseRoutes = new Elysia()
24+
.use(requireAuth)
2225
.put("/resume/:responseId", resumeResponse, resumeResponseDTO)
2326
.get("/my", getAllUserResponses)
2427
.get("/received", getAllReceivedResponses)
2528
.get("/:formId", getResponseForFormOwner, formResponseForFormOwnerDTO)
2629
.get("/user/:formId", getSubmittedResponse, getSubmittedResponseDTO);
30+
31+
export const formResponseRoutes = new Elysia({ prefix: "/responses" })
32+
.use(publicResponseRoutes)
33+
.use(protectedResponseRoutes);

src/integration_testing/form-response.integration.test.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,29 @@ describe("Form Response Integration Tests", () => {
2828
isSubmitted: true,
2929
};
3030

31-
it("returns 401 without authentication", async () => {
31+
it("allows submission without authentication", async () => {
3232
setAuthenticatedUser(null);
33+
prismaMock.form.findUnique.mockResolvedValue({
34+
id: UUID,
35+
isPublished: true,
36+
});
37+
prismaMock.formResponse.create.mockResolvedValue({
38+
id: RESPONSE_ID,
39+
formId: UUID,
40+
respondentId: null,
41+
answers: answerPayload.answers,
42+
isSubmitted: true,
43+
});
44+
3345
const res = await app.handle(
3446
request(`/responses/submit/${UUID}`, {
3547
method: "POST",
3648
body: jsonBody(answerPayload),
3749
}),
3850
);
39-
expect(res.status).toBe(401);
51+
expect(res.status).toBe(200);
52+
const data = await res.json();
53+
expect(data.success).toBe(true);
4054
});
4155

4256
it("submits a response successfully", async () => {

src/types/form-response.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ export interface Context {
55
set: { status?: number | string };
66
}
77

8+
export interface OptionalAuthContext {
9+
user: { id: string } | null;
10+
set: { status?: number | string };
11+
}
12+
813
export const formResponseDTO = {
914
params: t.Object({
1015
formId: t.String({
@@ -27,7 +32,7 @@ export const formResponseDTO = {
2732
}),
2833
};
2934

30-
export interface FormResponseContext extends Context {
35+
export interface FormResponseContext extends OptionalAuthContext {
3136
params: Static<typeof formResponseDTO.params>;
3237
body: Static<typeof formResponseDTO.body>;
3338
}

0 commit comments

Comments
 (0)