Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/features/add-todo/addToDoPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { describe, expect, test } from "bun:test";
import { createAppConfig } from "@shared/appConfig.ts";
import { createAppConfigMiddleware } from "@shared/appConfigMiddleware.ts";
import type { AppVariables } from "@shared/appVariables.ts";
import { pageRoutes } from "@shared/pageRoutes.ts";
import { Hono } from "hono";
import { sign } from "hono/jwt";
import { addToDoPage } from "./addToDoPage.tsx";

describe("addToDoPage", () => {
test("returns 401 when JWT cookie is missing", async () => {
test("redirects to login when JWT cookie is missing", async () => {
const appConfig = createAppConfig({
JWT_SECRET: "12345678901234567890123456789012",
});
Expand All @@ -17,7 +18,8 @@ describe("addToDoPage", () => {

const response = await app.fetch(new Request("http://localhost/"));

expect(response.status).toBe(401);
expect(response.status).toBe(302);
expect(response.headers.get("Location")).toBe(pageRoutes.LOGIN);
});

test("renders the add todo page HTML when JWT cookie is valid", async () => {
Expand Down
34 changes: 32 additions & 2 deletions src/features/home/homePage.test.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,43 @@
import { describe, expect, test } from "bun:test";
import { createAppConfig } from "@shared/appConfig.ts";
import { createAppConfigMiddleware } from "@shared/appConfigMiddleware.ts";
import type { AppVariables } from "@shared/appVariables.ts";
import { pageRoutes } from "@shared/pageRoutes.ts";
import { Hono } from "hono";
import { sign } from "hono/jwt";
import { homePage } from "./homePage.tsx";

describe("homePage", () => {
test("renders the home page HTML", async () => {
const app = new Hono<{ Variables: AppVariables }>().route("/", homePage);
test("redirects to login when JWT cookie is missing", async () => {
const appConfig = createAppConfig({
JWT_SECRET: "12345678901234567890123456789012",
});
const app = new Hono<{ Variables: AppVariables }>()
.use("*", createAppConfigMiddleware(appConfig))
.route("/", homePage);

const response = await app.fetch(new Request("http://localhost/"));

expect(response.status).toBe(302);
expect(response.headers.get("Location")).toBe(pageRoutes.LOGIN);
});

test("renders the home page HTML when JWT cookie is valid", async () => {
const appConfig = createAppConfig({
JWT_SECRET: "12345678901234567890123456789012",
});
const token = await sign({ sub: "admin" }, appConfig.jwt.secret, "HS256");
const app = new Hono<{ Variables: AppVariables }>()
.use("*", createAppConfigMiddleware(appConfig))
.route("/", homePage);

const response = await app.fetch(
new Request("http://localhost/", {
headers: {
Cookie: `${appConfig.jwt.cookieName}=${token}`,
},
}),
);
const html = await response.text();

expect(response.status).toBe(200);
Expand Down
10 changes: 5 additions & 5 deletions src/features/home/homePage.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import type { AppVariables } from "@shared/appVariables.ts";
import { Page } from "@shared/page.tsx";
import { pageJwtMiddleware } from "@shared/pageJwtMiddleware.ts";
import { Hono } from "hono";

export const homePage = new Hono<{ Variables: AppVariables }>().get(
"/",
(c) => {
export const homePage = new Hono<{ Variables: AppVariables }>()
.use("/", pageJwtMiddleware)
.get("/", (c) => {
return c.html(
<Page>
<h1>Home</h1>
</Page>,
);
},
);
});
34 changes: 30 additions & 4 deletions src/shared/pageJwtMiddleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import { sign } from "hono/jwt";
import { createAppConfig } from "./appConfig.ts";
import { createAppConfigMiddleware } from "./appConfigMiddleware.ts";
import { pageJwtMiddleware } from "./pageJwtMiddleware.ts";
import { pageRoutes } from "./pageRoutes.ts";

describe("pageJwtMiddleware", () => {
test("returns 401 when JWT cookie is missing", async () => {
test("redirects to login when JWT cookie is missing", async () => {
const appConfig = createAppConfig({
JWT_SECRET: "12345678901234567890123456789012",
});
Expand All @@ -18,10 +19,11 @@ describe("pageJwtMiddleware", () => {

const response = await app.fetch(new Request("http://localhost/"));

expect(response.status).toBe(401);
expect(response.status).toBe(302);
expect(response.headers.get("Location")).toBe(pageRoutes.LOGIN);
});
Comment thread
CharlesFarris marked this conversation as resolved.

test("returns 401 when JWT cookie is invalid", async () => {
test("redirects to login when JWT cookie is invalid", async () => {
const appConfig = createAppConfig({
JWT_SECRET: "12345678901234567890123456789012",
});
Expand All @@ -38,7 +40,8 @@ describe("pageJwtMiddleware", () => {
}),
);

expect(response.status).toBe(401);
expect(response.status).toBe(302);
expect(response.headers.get("Location")).toBe(pageRoutes.LOGIN);
});

test("calls next when JWT cookie is valid", async () => {
Expand Down Expand Up @@ -66,4 +69,27 @@ describe("pageJwtMiddleware", () => {
expect(response.status).toBe(200);
expect(handlerReached).toBe(true);
});

test("does not redirect when downstream handler throws", async () => {
const appConfig = createAppConfig({
JWT_SECRET: "12345678901234567890123456789012",
});
const token = await sign({ sub: "admin" }, appConfig.jwt.secret, "HS256");
const app = new Hono<{ Variables: AppVariables }>()
.use("*", createAppConfigMiddleware(appConfig))
.use("*", pageJwtMiddleware)
.get("/", () => {
throw new Error("handler failed");
});

const response = await app.fetch(
new Request("http://localhost/", {
headers: {
Cookie: `${appConfig.jwt.cookieName}=${token}`,
},
}),
);

expect(response.status).toBe(500);
});
});
14 changes: 12 additions & 2 deletions src/shared/pageJwtMiddleware.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import { createMiddleware } from "hono/factory";
import { jwt } from "hono/jwt";
import type { AppVariables } from "./appVariables.ts";
import { pageRoutes } from "./pageRoutes.ts";

export const pageJwtMiddleware = createMiddleware<{ Variables: AppVariables }>(
async (c, next) => {
const appConfig = c.var.appConfig;
return await jwt({
const verifyJwt = jwt({
secret: appConfig.jwt.secret,
cookie: appConfig.jwt.cookieName,
alg: "HS256",
})(c, next);
});

try {
await verifyJwt(c, async () => {});
} catch {
return c.redirect(pageRoutes.LOGIN);
}
Comment thread
CharlesFarris marked this conversation as resolved.

await next();
return;
},
);