Merge commit '3c60637c1a27da8ba66888de518d58d5707801f2' as 'repos/effect-smol'
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import { assert, describe, it } from "@effect/vitest"
|
||||
import { Effect, Encoding, Redacted } from "effect"
|
||||
import { HttpClientRequest, HttpServerRequest } from "effect/unstable/http"
|
||||
import { HttpApiBuilder, HttpApiSecurity } from "effect/unstable/httpapi"
|
||||
|
||||
const decode = <Security extends HttpApiSecurity.HttpApiSecurity>(authorization: string, security: Security) =>
|
||||
HttpApiBuilder.securityDecode(security).pipe(
|
||||
Effect.provideService(
|
||||
HttpServerRequest.HttpServerRequest,
|
||||
HttpServerRequest.fromWeb(new Request("http://localhost/", { headers: { authorization } }))
|
||||
),
|
||||
Effect.provideService(HttpServerRequest.ParsedSearchParams, {})
|
||||
)
|
||||
|
||||
describe("HttpApiSecurity", () => {
|
||||
describe("securityDecode", () => {
|
||||
it.effect("decodes a bearer token without a leading space", () =>
|
||||
Effect.gen(function*() {
|
||||
const token = "abc123"
|
||||
const { headers } = HttpClientRequest.get("http://localhost/").pipe(
|
||||
HttpClientRequest.bearerToken(token)
|
||||
)
|
||||
const credential = yield* HttpApiBuilder.securityDecode(HttpApiSecurity.bearer).pipe(
|
||||
Effect.provideService(
|
||||
HttpServerRequest.HttpServerRequest,
|
||||
HttpServerRequest.fromWeb(new Request("http://localhost/", { headers }))
|
||||
),
|
||||
Effect.provideService(HttpServerRequest.ParsedSearchParams, {})
|
||||
)
|
||||
|
||||
assert.strictEqual(Redacted.value(credential), token)
|
||||
}))
|
||||
|
||||
it.effect("decodes a custom http scheme without a leading space", () =>
|
||||
Effect.gen(function*() {
|
||||
const credential = yield* decode("Token abc123", HttpApiSecurity.http({ scheme: "Token" }))
|
||||
|
||||
assert.strictEqual(Redacted.value(credential), "abc123")
|
||||
}))
|
||||
|
||||
it.effect("matches HTTP schemes case-insensitively", () =>
|
||||
Effect.gen(function*() {
|
||||
const credential = yield* decode("bEaReR abc123", HttpApiSecurity.bearer)
|
||||
|
||||
assert.strictEqual(Redacted.value(credential), "abc123")
|
||||
}))
|
||||
|
||||
it.effect("accepts multiple spaces before HTTP credentials", () =>
|
||||
Effect.gen(function*() {
|
||||
const credential = yield* decode("Bearer abc123", HttpApiSecurity.bearer)
|
||||
|
||||
assert.strictEqual(Redacted.value(credential), "abc123")
|
||||
}))
|
||||
|
||||
it.effect("rejects mismatched and malformed HTTP schemes", () =>
|
||||
Effect.gen(function*() {
|
||||
const mismatched = yield* decode("Basic abc123", HttpApiSecurity.bearer)
|
||||
const malformed = yield* decode("Bearerabc123", HttpApiSecurity.bearer)
|
||||
|
||||
assert.strictEqual(Redacted.value(mismatched), "")
|
||||
assert.strictEqual(Redacted.value(malformed), "")
|
||||
}))
|
||||
|
||||
it.effect("decodes Basic credentials using the first colon separator", () =>
|
||||
Effect.gen(function*() {
|
||||
const encoded = Encoding.encodeBase64("alice:secret:with:colons")
|
||||
const credential = yield* decode(`Basic ${encoded}`, HttpApiSecurity.basic)
|
||||
|
||||
assert.strictEqual(credential.username, "alice")
|
||||
assert.strictEqual(Redacted.value(credential.password), "secret:with:colons")
|
||||
}))
|
||||
|
||||
it.effect("rejects Basic credentials from a different scheme", () =>
|
||||
Effect.gen(function*() {
|
||||
const encoded = Encoding.encodeBase64("alice:secret")
|
||||
const credential = yield* decode(`Bearer ${encoded}`, HttpApiSecurity.basic)
|
||||
|
||||
assert.strictEqual(credential.username, "")
|
||||
assert.strictEqual(Redacted.value(credential.password), "")
|
||||
}))
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user