-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Finalize authenticate middleware (#7)
- Loading branch information
Showing
7 changed files
with
144 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { describe, expect, it } from "vitest"; | ||
import { createTestContext } from "../../helpers/testHelpers/createTestContext"; | ||
import { authenticate } from "./authenticate"; | ||
|
||
const mw = authenticate(async (context) => { | ||
const authorization = context.request.getHeader("authorization"); | ||
|
||
return authorization === null | ||
? { type: "unset" } | ||
: { type: "set", session: authorization }; | ||
}); | ||
|
||
describe("authenticate", () => { | ||
it("sets the session returned by handler", async () => { | ||
const result = await mw( | ||
createTestContext({ | ||
requestHeaders: { authorization: "some authorization" }, | ||
}) | ||
); | ||
expect(result.response).toEqual({ type: "unset" }); | ||
expect(result.session).toBe("some authorization"); | ||
}); | ||
|
||
it("returns 401 if handler doesn't set a session", async () => { | ||
const result = await mw(createTestContext()); | ||
expect(result.response).toEqual({ | ||
type: "set", | ||
body: { error: "Unauthorized" }, | ||
statusCode: 401, | ||
headers: {}, | ||
}); | ||
}); | ||
|
||
it("merges request headers", async () => { | ||
const context = createTestContext({ | ||
response: { | ||
type: "partially-set", | ||
headers: { "Some-Header": "some value" }, | ||
}, | ||
}); | ||
|
||
const result = await mw(context); | ||
|
||
expect(result.response).toEqual({ | ||
type: "set", | ||
body: { error: "Unauthorized" }, | ||
statusCode: 401, | ||
headers: { "Some-Header": "some value" }, | ||
}); | ||
}); | ||
|
||
it("doesn't set a response if response is already set", async () => { | ||
const context = createTestContext({ | ||
response: { type: "set", body: null, statusCode: 200, headers: {} }, | ||
}); | ||
const result = await mw(context); | ||
expect(result.response).toBe(context.response); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,43 @@ | ||
import { BasePipelineContext } from "../../../createPipeline/helpers/types"; | ||
import { AuthenticateContext } from "./types"; | ||
import { | ||
AuthenticateCallbackResult, | ||
AuthenticateContext, | ||
UnauthorizedResponseBody, | ||
} from "./types"; | ||
|
||
export function reply(context: BasePipelineContext): AuthenticateContext { | ||
return { | ||
...context, | ||
user: "stuffs", | ||
} as AuthenticateContext; | ||
export function reply<Session>( | ||
context: BasePipelineContext, | ||
result: AuthenticateCallbackResult<Session> | ||
): AuthenticateContext<Session> { | ||
if (context.response.type === "set") { | ||
return { | ||
...context, | ||
session: null, | ||
} as AuthenticateContext<Session>; | ||
} | ||
|
||
switch (result.type) { | ||
case "set": { | ||
return { | ||
...context, | ||
session: result.session, | ||
} as AuthenticateContext<Session>; | ||
} | ||
case "unset": { | ||
return { | ||
...context, | ||
session: null, // TODO not great | ||
response: { | ||
type: "set", | ||
body: { error: "Unauthorized" } satisfies UnauthorizedResponseBody, | ||
statusCode: 401, | ||
headers: { | ||
...(context.response.type !== "unset" | ||
? context.response.headers | ||
: {}), | ||
}, | ||
}, | ||
} as AuthenticateContext<Session>; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,26 @@ | ||
import { BasePipelineContext } from "../../../createPipeline/helpers/types"; | ||
|
||
// TODO how to make this configurable? | ||
export type UnauthorizedResponseBody = { error: "Unauthorized" }; | ||
|
||
type AuthenticateCustomMiddlewareResponse = { | ||
authenticateCustomMiddlewareResponse: { | ||
statusCode: 401; | ||
body: { error: "Unauthorized" }; | ||
body: UnauthorizedResponseBody; | ||
}; | ||
}; | ||
|
||
export type AuthenticateContextExtension = { | ||
user: string; | ||
export type AuthenticateContextExtension<Session> = { | ||
session: Session; | ||
} & AuthenticateCustomMiddlewareResponse; | ||
|
||
export type AuthenticateContext = BasePipelineContext & | ||
AuthenticateContextExtension; | ||
export type AuthenticateContext<Session> = BasePipelineContext & | ||
AuthenticateContextExtension<Session>; | ||
|
||
export type AuthenticateCallbackResult<Session> = | ||
| { type: "set"; session: Session } | ||
| { type: "unset" }; | ||
|
||
export type AuthenticateCallback<In extends BasePipelineContext, Session> = ( | ||
context: In | ||
) => Promise<AuthenticateCallbackResult<Session>>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters