Merge pull request #1214 from pikasTech/fix/issue-1211-user-billing-session-token

#1211 R4:修复 user-billing session summary 代理
This commit is contained in:
Lyon
2026-06-14 15:57:38 +08:00
committed by GitHub
2 changed files with 25 additions and 3 deletions
+2 -2
View File
@@ -991,9 +991,9 @@ async function handleUsageSummaryHttp(request, response, url, options) {
const nextOptions = await codeAgentOptions(request, response, options, { required: true });
if (!nextOptions) return;
const client = nextOptions.userBillingClient;
const token = bearerTokenFromRequest(request);
const token = userBillingTokenFromRequest(request);
if (nextOptions.userBillingAuth?.active !== true || !token) {
sendRestError(request, response, 403, "user_billing_auth_required", "usage summary requires a user-billing bearer token", {
sendRestError(request, response, 403, "user_billing_auth_required", "usage summary requires a user-billing session or API key", {
operation: `GET ${route}`,
target: { type: "route", id: route },
result: "rejected"
@@ -878,6 +878,20 @@ test("cloud api bridges user-billing register/login into HttpOnly web session co
calls.push({ op: "listApiKeys", tokenPrefix: token.slice(0, 8) });
assert.equal(token, sessionToken);
return { ok: true, status: 200, body: { contractVersion: "user-api-key-v1", keys: [{ id: "key_web_session", name: "Web session key", prefix: "hwl_web" }], count: 1 } };
},
async billingSummary(token, query = {}) {
calls.push({ op: "billingSummary", tokenPrefix: token.slice(0, 8), query });
assert.equal(token, sessionToken);
return {
ok: true,
status: 200,
body: {
contractVersion: "user-billing-summary-v1",
planId: "default",
entitlements: [{ resourceType: "code_agent", enabled: true }],
valuesRedacted: true
}
};
}
};
const server = createCloudApiServer({ env: { HWLAB_ACCESS_CONTROL_REQUIRED: "1" }, userBillingClient });
@@ -905,13 +919,21 @@ test("cloud api bridges user-billing register/login into HttpOnly web session co
assert.equal(sessionBody.actor.username, "new-user");
assert.equal(JSON.stringify(sessionBody).includes(sessionToken), false);
const billingSummary = await fetch(`http://127.0.0.1:${port}/v1/billing/summary?limit=3`, { headers: { cookie } });
assert.equal(billingSummary.status, 200);
const billingSummaryBody = await billingSummary.json();
assert.equal(billingSummaryBody.planId, "default");
assert.equal(billingSummaryBody.entitlements[0].resourceType, "code_agent");
assert.equal(billingSummaryBody.proxy.source, "hwlab-user-billing");
assert.equal(JSON.stringify(billingSummaryBody).includes(sessionToken), false);
const keys = await fetch(`http://127.0.0.1:${port}/v1/api-keys`, { headers: { cookie } });
assert.equal(keys.status, 200);
const keysBody = await keys.json();
assert.equal(keysBody.proxy.source, "hwlab-user-billing");
assert.equal(keysBody.keys[0].id, "key_web_session");
assert.equal(JSON.stringify(keysBody).includes(sessionToken), false);
assert.deepEqual(calls.map((call) => call.op), ["register", "login", "introspect", "introspect", "introspect", "listApiKeys"]);
assert.deepEqual(calls.map((call) => call.op), ["register", "login", "introspect", "introspect", "introspect", "billingSummary", "introspect", "listApiKeys"]);
} finally {
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
}