mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-13 21:01:21 +08:00
* Add in-source unit tests to stack-shared utilities Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Fix type checking and linting issues Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Fix lint errors in results.tsx Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Fix remaining lint errors in results.tsx Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Fix lint warnings in results.tsx Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Fix wait function mocking in results.tsx Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Fix retry function test in results.tsx Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Fix React.forwardRef mock in react.tsx test Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Fix trailing spaces in react.tsx and results.tsx Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Revert to DependenciesMap and wrap rejected promise in ignoreUnhandledRejection Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Fix * Revert changes to known-errors.tsx constructor Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Make rotateRight call rotateLeft per review feedback Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Remove redundant @ts-expect-error directive in known-errors.tsx Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Fix import order in promises.tsx Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Fix * Fix CI failures: add back @ts-expect-error in known-errors.tsx and revert mapResult implementation in results.tsx Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Remove unused @ts-expect-error directive in known-errors.tsx Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Add back @ts-expect-error directive with explanation in known-errors.tsx Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * Change @ts-expect-error to @ts-ignore in known-errors.tsx Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com> * be honest * vocabulary --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Konstantin Wohlwend <n2d4xc@gmail.com>
92 lines
3.1 KiB
TypeScript
92 lines
3.1 KiB
TypeScript
import { decodeBase64, encodeBase64, isBase64 } from "./bytes";
|
|
|
|
export const HTTP_METHODS = {
|
|
"GET": {
|
|
safe: true,
|
|
idempotent: true,
|
|
},
|
|
"POST": {
|
|
safe: false,
|
|
idempotent: false,
|
|
},
|
|
"PUT": {
|
|
safe: false,
|
|
idempotent: true,
|
|
},
|
|
"DELETE": {
|
|
safe: false,
|
|
idempotent: true,
|
|
},
|
|
"PATCH": {
|
|
safe: false,
|
|
idempotent: false,
|
|
},
|
|
"OPTIONS": {
|
|
safe: true,
|
|
idempotent: true,
|
|
},
|
|
"HEAD": {
|
|
safe: true,
|
|
idempotent: true,
|
|
},
|
|
"TRACE": {
|
|
safe: true,
|
|
idempotent: true,
|
|
},
|
|
"CONNECT": {
|
|
safe: false,
|
|
idempotent: false,
|
|
},
|
|
} as const;
|
|
export type HttpMethod = keyof typeof HTTP_METHODS;
|
|
|
|
export function decodeBasicAuthorizationHeader(value: string): [string, string] | null {
|
|
const [type, encoded, ...rest] = value.split(' ');
|
|
if (rest.length > 0) return null;
|
|
if (!encoded) return null;
|
|
if (type !== 'Basic') return null;
|
|
if (!isBase64(encoded)) return null;
|
|
const decoded = new TextDecoder().decode(decodeBase64(encoded));
|
|
const split = decoded.split(':');
|
|
return [split[0], split.slice(1).join(':')];
|
|
}
|
|
import.meta.vitest?.test("decodeBasicAuthorizationHeader", ({ expect }) => {
|
|
// Test with valid Basic Authorization header
|
|
const username = "user";
|
|
const password = "pass";
|
|
const encoded = encodeBasicAuthorizationHeader(username, password);
|
|
expect(decodeBasicAuthorizationHeader(encoded)).toEqual([username, password]);
|
|
|
|
// Test with password containing colons
|
|
const complexPassword = "pass:with:colons";
|
|
const encodedComplex = encodeBasicAuthorizationHeader(username, complexPassword);
|
|
expect(decodeBasicAuthorizationHeader(encodedComplex)).toEqual([username, complexPassword]);
|
|
|
|
// Test with invalid headers
|
|
expect(decodeBasicAuthorizationHeader("NotBasic dXNlcjpwYXNz")).toBe(null); // Wrong type
|
|
expect(decodeBasicAuthorizationHeader("Basic")).toBe(null); // Missing encoded part
|
|
expect(decodeBasicAuthorizationHeader("Basic not-base64")).toBe(null); // Not base64
|
|
expect(decodeBasicAuthorizationHeader("Basic dXNlcjpwYXNz extra")).toBe(null); // Extra parts
|
|
});
|
|
|
|
export function encodeBasicAuthorizationHeader(id: string, password: string): string {
|
|
if (id.includes(':')) throw new Error("Basic authorization header id cannot contain ':'");
|
|
return `Basic ${encodeBase64(new TextEncoder().encode(`${id}:${password}`))}`;
|
|
}
|
|
import.meta.vitest?.test("encodeBasicAuthorizationHeader", ({ expect }) => {
|
|
// Test with simple username and password
|
|
const encoded = encodeBasicAuthorizationHeader("user", "pass");
|
|
expect(encoded).toMatch(/^Basic [A-Za-z0-9+/=]+$/); // Should start with "Basic " followed by base64
|
|
|
|
// Test with empty password
|
|
const encodedEmptyPass = encodeBasicAuthorizationHeader("user", "");
|
|
expect(encodedEmptyPass).toMatch(/^Basic [A-Za-z0-9+/=]+$/);
|
|
|
|
// Test with password containing special characters
|
|
const encodedSpecialChars = encodeBasicAuthorizationHeader("user", "p@ss!w0rd");
|
|
expect(encodedSpecialChars).toMatch(/^Basic [A-Za-z0-9+/=]+$/);
|
|
|
|
// Test with username containing colon should throw
|
|
expect(() => encodeBasicAuthorizationHeader("user:name", "pass")).toThrow();
|
|
});
|