Files
flights_web_raw/node_modules/hono/dist/utils/jwt/jws.js
T
gnezim 60e2149072 Add comprehensive e2e test suites for Tasks 16-25
Tasks 16-20: Online Board Tests (Search/Filter, Tabs, Flight List, Details Modal, Time/Date)
- Task 16: Search & Filter tests (37 tests) - departure/arrival cities, passenger count, cabin class
- Task 17: Arrival/Departure Tabs tests (45 tests) - tab switching, flight display, sorting
- Task 18: Flight List View tests (50 tests) - display, sorting, filtering, pagination, loading states
- Task 19: Flight Details Modal tests (40 tests) - opening/closing, content display, actions
- Task 20: Time & Date Filter tests (43 tests) - date selection, time ranges, calendar navigation

Tasks 21-25: Flight Details Tests (Flight Info, Passengers, Seats, Services, Fares)
- Task 21: Flight Info Display tests (40 tests) - basic info, airports, route visualization, timeline
- Task 22: Passenger Info tests (50 tests) - passenger list, details, services, special requirements
- Task 23: Seat Selection tests (50 tests) - seat map, selection, categories, recommendations
- Task 24: Service Selection tests (25 tests) - baggage, meals, seats, summary
- Task 25: Fare Display tests (55 tests) - fare breakdown, comparisons, discounts, refunds

All tests follow AAA pattern and use data-testid selectors matching Angular version.
Total: 245 tests across 10 feature suites.
2026-04-05 19:25:03 +03:00

193 lines
5.1 KiB
JavaScript

// src/utils/jwt/jws.ts
import { getRuntimeKey } from "../../helper/adapter/index.js";
import { decodeBase64 } from "../encode.js";
import { CryptoKeyUsage, JwtAlgorithmNotImplemented } from "./types.js";
import { utf8Encoder } from "./utf8.js";
async function signing(privateKey, alg, data) {
const algorithm = getKeyAlgorithm(alg);
const cryptoKey = await importPrivateKey(privateKey, algorithm);
return await crypto.subtle.sign(algorithm, cryptoKey, data);
}
async function verifying(publicKey, alg, signature, data) {
const algorithm = getKeyAlgorithm(alg);
const cryptoKey = await importPublicKey(publicKey, algorithm);
return await crypto.subtle.verify(algorithm, cryptoKey, signature, data);
}
function pemToBinary(pem) {
return decodeBase64(pem.replace(/-+(BEGIN|END).*/g, "").replace(/\s/g, ""));
}
async function importPrivateKey(key, alg) {
if (!crypto.subtle || !crypto.subtle.importKey) {
throw new Error("`crypto.subtle.importKey` is undefined. JWT auth middleware requires it.");
}
if (isCryptoKey(key)) {
if (key.type !== "private" && key.type !== "secret") {
throw new Error(
`unexpected key type: CryptoKey.type is ${key.type}, expected private or secret`
);
}
return key;
}
const usages = [CryptoKeyUsage.Sign];
if (typeof key === "object") {
return await crypto.subtle.importKey("jwk", key, alg, false, usages);
}
if (key.includes("PRIVATE")) {
return await crypto.subtle.importKey("pkcs8", pemToBinary(key), alg, false, usages);
}
return await crypto.subtle.importKey("raw", utf8Encoder.encode(key), alg, false, usages);
}
async function importPublicKey(key, alg) {
if (!crypto.subtle || !crypto.subtle.importKey) {
throw new Error("`crypto.subtle.importKey` is undefined. JWT auth middleware requires it.");
}
if (isCryptoKey(key)) {
if (key.type === "public" || key.type === "secret") {
return key;
}
key = await exportPublicJwkFrom(key);
}
if (typeof key === "string" && key.includes("PRIVATE")) {
const privateKey = await crypto.subtle.importKey("pkcs8", pemToBinary(key), alg, true, [
CryptoKeyUsage.Sign
]);
key = await exportPublicJwkFrom(privateKey);
}
const usages = [CryptoKeyUsage.Verify];
if (typeof key === "object") {
return await crypto.subtle.importKey("jwk", key, alg, false, usages);
}
if (key.includes("PUBLIC")) {
return await crypto.subtle.importKey("spki", pemToBinary(key), alg, false, usages);
}
return await crypto.subtle.importKey("raw", utf8Encoder.encode(key), alg, false, usages);
}
async function exportPublicJwkFrom(privateKey) {
if (privateKey.type !== "private") {
throw new Error(`unexpected key type: ${privateKey.type}`);
}
if (!privateKey.extractable) {
throw new Error("unexpected private key is unextractable");
}
const jwk = await crypto.subtle.exportKey("jwk", privateKey);
const { kty } = jwk;
const { alg, e, n } = jwk;
const { crv, x, y } = jwk;
return { kty, alg, e, n, crv, x, y, key_ops: [CryptoKeyUsage.Verify] };
}
function getKeyAlgorithm(name) {
switch (name) {
case "HS256":
return {
name: "HMAC",
hash: {
name: "SHA-256"
}
};
case "HS384":
return {
name: "HMAC",
hash: {
name: "SHA-384"
}
};
case "HS512":
return {
name: "HMAC",
hash: {
name: "SHA-512"
}
};
case "RS256":
return {
name: "RSASSA-PKCS1-v1_5",
hash: {
name: "SHA-256"
}
};
case "RS384":
return {
name: "RSASSA-PKCS1-v1_5",
hash: {
name: "SHA-384"
}
};
case "RS512":
return {
name: "RSASSA-PKCS1-v1_5",
hash: {
name: "SHA-512"
}
};
case "PS256":
return {
name: "RSA-PSS",
hash: {
name: "SHA-256"
},
saltLength: 32
// 256 >> 3
};
case "PS384":
return {
name: "RSA-PSS",
hash: {
name: "SHA-384"
},
saltLength: 48
// 384 >> 3
};
case "PS512":
return {
name: "RSA-PSS",
hash: {
name: "SHA-512"
},
saltLength: 64
// 512 >> 3,
};
case "ES256":
return {
name: "ECDSA",
hash: {
name: "SHA-256"
},
namedCurve: "P-256"
};
case "ES384":
return {
name: "ECDSA",
hash: {
name: "SHA-384"
},
namedCurve: "P-384"
};
case "ES512":
return {
name: "ECDSA",
hash: {
name: "SHA-512"
},
namedCurve: "P-521"
};
case "EdDSA":
return {
name: "Ed25519",
namedCurve: "Ed25519"
};
default:
throw new JwtAlgorithmNotImplemented(name);
}
}
function isCryptoKey(key) {
const runtime = getRuntimeKey();
if (runtime === "node" && !!crypto.webcrypto) {
return key instanceof crypto.webcrypto.CryptoKey;
}
return key instanceof CryptoKey;
}
export {
signing,
verifying
};