初始化提交:go比特版本精简

This commit is contained in:
2026-09-20 17:02:11 +08:00
commit f41a979462
213 changed files with 58288 additions and 0 deletions
+401
View File
@@ -0,0 +1,401 @@
'use strict';
const assert = require('assert');
const {
extractAccessToken,
tokenInfo,
parseUserSession,
createWorkspaceRefundClient,
executeWorkspaceRefund,
safeWorkspaceRefundFailure,
_private: refundPrivate,
} = require('../src/services/workspace_refund_service');
function jwt(payload) {
const encode = value => Buffer.from(JSON.stringify(value)).toString('base64url');
return `${encode({ alg: 'none', typ: 'JWT' })}.${encode(payload)}.signature`;
}
function makeToken({ email, userId, accountId, exp = Math.floor(Date.now() / 1000) + 3600 }) {
return jwt({
sub: userId,
exp,
'https://api.openai.com/profile': { email, name: email.split('@')[0] },
'https://api.openai.com/auth': {
chatgpt_user_id: userId,
chatgpt_account_id: accountId,
chatgpt_plan_type: accountId.startsWith('team-') ? 'team' : 'plus',
},
});
}
function response(status, data = {}) {
return {
ok: status >= 200 && status < 300,
status,
text: async () => JSON.stringify(data),
};
}
(async () => {
const adminToken = makeToken({
email: 'owner@gmail.com',
userId: 'owner-user',
accountId: 'team-001',
});
const userToken = makeToken({
email: 'Target.User@gmail.com',
userId: 'target-user',
accountId: 'personal-001',
});
const session = JSON.stringify({
user: { email: 'targetuser@gmail.com', name: 'Target' },
accessToken: userToken,
expires: new Date(Date.now() + 3600000).toISOString(),
});
assert.strictEqual(extractAccessToken(adminToken), adminToken);
assert.strictEqual(extractAccessToken(JSON.stringify({ accessToken: adminToken })), adminToken);
assert.strictEqual(tokenInfo(adminToken).accountId, 'team-001');
assert.doesNotThrow(
() => parseUserSession(session, 'Target.User.@gmail.com'),
'退款 Session 的二次 JWT 校验也必须遵循 Gmail 忽略点号规则',
);
let proxyFactoryInput = '';
const proxyCalls = [];
const proxyClient = createWorkspaceRefundClient({
proxy: 'socks5://user:pass@127.0.0.1:1080',
createProxyRequester(proxy) {
proxyFactoryInput = proxy;
return {
async request(url, options) {
proxyCalls.push({ url, options });
return { ok: true, status: 200, data: { users: [] }, text: '{"users":[]}' };
},
};
},
});
const proxyResponse = await proxyClient.request('/accounts/team-001/users', {
token: adminToken,
accountId: 'team-001',
});
assert.strictEqual(proxyResponse.ok, true);
assert.strictEqual(proxyFactoryInput, 'socks5://user:pass@127.0.0.1:1080');
assert.strictEqual(proxyCalls.length, 1);
assert.strictEqual(proxyCalls[0].options.headers.Authorization, `Bearer ${adminToken}`);
assert.match(proxyCalls[0].url, /\/backend-api\/accounts\/team-001\/users$/);
const poolProxy1 = 'socks5://user:pass@127.0.0.11:1080';
const poolProxy2 = 'socks5://user:pass@127.0.0.12:1080';
const poolCalls = [];
const poolLogs = [];
const poolClient = createWorkspaceRefundClient({
proxies: [poolProxy1, poolProxy2],
onProxyLog: message => poolLogs.push(message),
createProxyRequester(proxy) {
return {
async request() {
poolCalls.push(proxy);
if (proxy === poolProxy1) {
return {
ok: false,
status: 403,
data: null,
text: '<html>Enable JavaScript and cookies to continue</html>',
};
}
return { ok: true, status: 200, data: { users: [] }, text: '{"users":[]}' };
},
};
},
});
assert.strictEqual((await poolClient.request('/accounts/team-001/users', {
token: adminToken,
accountId: 'team-001',
})).ok, true);
assert.deepStrictEqual(poolCalls, [poolProxy1, poolProxy2]);
assert(poolLogs.some(message => /1\/2.*Cloudflare.*切换下一条/.test(message)));
await poolClient.request('/accounts/team-001/users', { token: adminToken, accountId: 'team-001' });
assert.deepStrictEqual(poolCalls, [poolProxy1, poolProxy2, poolProxy2],
'成功的代理应在后续退款请求中继续复用');
const calls = [];
const replies = [
response(200, { users: [
{ user_id: 'owner-user', role: 'owner' },
{ user_id: 'old-member', role: 'standard-user' },
] }),
response(200, {}),
response(200, { users: [
{ user_id: 'owner-user', role: 'owner' },
] }),
response(200, {
seat_capacity: [
{ type: 'default', available: 0 },
{ type: 'prolite', available: 1 },
],
seats_in_use: 1,
seats_entitled: 2,
}),
response(201, {}),
response(409, { detail: 'seat pending' }),
response(200, {}),
response(200, { users: [
{ user_id: 'owner-user', role: 'owner' },
{ user_id: 'target-user', email: 'target.user@gmail.com', role: 'standard-user' },
] }),
response(200, {}),
response(204, {}),
];
const progress = [];
const sleepDelays = [];
const result = await executeWorkspaceRefund({
adminAccessToken: adminToken,
userSessionText: session,
expectedEmail: 'Target.User@gmail.com',
fetchImpl: async (url, options) => {
calls.push({ url, method: options.method, headers: options.headers, body: options.body });
const next = replies.shift();
if (!next) throw new Error('unexpected request');
return next;
},
random: () => 0.5,
sleep: async delay => { sleepDelays.push(delay); },
onProgress: item => progress.push(item.message),
});
assert.strictEqual(result.success, true);
assert.strictEqual(result.cleanupOk, true);
assert.strictEqual(result.removedMembers, 1);
assert.strictEqual(calls.length, 10);
assert.match(calls[0].url, /\/accounts\/team-001\/users$/);
assert.strictEqual(calls[1].method, 'DELETE');
assert(!calls.some(call => /owner-user$/.test(call.url) && call.method === 'DELETE'), '不得移除母号 Owner');
assert.match(calls[4].url, /\/invites$/);
assert.strictEqual(JSON.parse(calls[4].body).seat_type, 'prolite',
'default 无空位时必须自动使用可用的 prolite 席位发出邀请');
assert(progress.some(message => message.startsWith('邀请接口返回 HTTP 201')));
assert.match(calls[8].url, /\/accounts\/transfer$/);
assert.match(calls[9].url, /\/users\/target-user$/);
assert(calls.every(call => !JSON.stringify(call).includes('signature') || call.headers.Authorization),
'Token 只能存在 Authorization 请求头中');
assert(progress.includes('正在迁移并去除个人空间'));
assert(progress.includes('接受接口返回 HTTP 200,等待 8 秒确认团队成员状态'));
assert(sleepDelays.includes(7500), '接受邀请后应随机等待 5–10 秒再迁移个人空间');
const realMemberCalls = [];
await assert.rejects(
executeWorkspaceRefund({
adminAccessToken: adminToken,
userSessionText: session,
expectedEmail: 'Target.User@gmail.com',
client: {
async request(path, options) {
realMemberCalls.push({ path, method: options.method });
if (/\/users\/account-member$/.test(path) && options.method === 'DELETE') {
return { ok: true, status: 204, data: {} };
}
if (/\/accounts\/team-001\/users$/.test(path)) {
const afterCleanup = realMemberCalls.some(call => /\/users\/account-member$/.test(call.path));
return { ok: true, status: 200, data: { users: afterCleanup ? [
{ account_user_id: 'account-owner-current', id: 'owner-user', role: 'account-owner' },
{ account_user_id: 'account-owner-other', id: 'other-owner', role: 'account-owner' },
] : [
{ account_user_id: 'account-owner-current', id: 'owner-user', role: 'account-owner' },
{ account_user_id: 'account-owner-other', id: 'other-owner', role: 'account-owner' },
{ account_user_id: 'account-member', id: 'legacy-member-id', role: 'standard-user' },
] } };
}
if (/\/subscriptions\?/.test(path)) {
return {
ok: true,
status: 200,
data: {
seats_in_use: 2,
seats_entitled: 2,
seat_capacity: [
{ type: 'default', available: 0 },
{ type: 'prolite', available: 0 },
],
},
};
}
throw new Error(`unexpected request: ${path}`);
},
},
sleep: async () => {},
}),
error => error
&& error.code === 'REFUND_NO_AVAILABLE_SEAT'
&& /已使用 2\/2/.test(error.message)
&& /剩余 2 个所有者/.test(error.message),
);
assert(realMemberCalls.some(call => /\/users\/account-member$/.test(call.path)),
'真实团队成员结构必须优先使用 account_user_id 删除');
assert(!realMemberCalls.some(call => /account-owner-(?:current|other)$/.test(call.path)),
'不得自动删除任何 account-owner');
assert.match(
safeWorkspaceRefundFailure({
code: 'REFUND_NO_AVAILABLE_SEAT',
message: '母号团队没有可用座位(已使用 2/2;剩余 2 个所有者)',
}).message,
/已使用 2\/2;剩余 2 个所有者/,
);
const fallbackOldToken = makeToken({
email: 'fallback.user@gmail.com',
userId: 'fallback-user',
accountId: 'personal-fallback',
exp: Math.floor(Date.now() / 1000) - 10,
});
const fallbackNewToken = makeToken({
email: 'fallback.user@gmail.com',
userId: 'fallback-user',
accountId: 'personal-fallback',
exp: Math.floor(Date.now() / 1000) + 7200,
});
const fallbackSession = JSON.stringify({
user: { email: 'fallback.user@gmail.com' },
accessToken: fallbackOldToken,
sessionToken: 'fallback-session-token',
});
const fallbackUpdates = [];
const fallbackTransferAccountIds = [];
let fallbackAccepted = false;
const fallbackResult = await executeWorkspaceRefund({
adminAccessToken: adminToken,
userSessionText: fallbackSession,
userAuthJsonText: '',
expectedEmail: 'fallbackuser@gmail.com',
client: {
async request(path, options) {
if (/\/accounts\/team-001\/users$/.test(path)) {
return {
ok: true,
status: 200,
data: { users: fallbackAccepted ? [
{ user_id: 'fallback-user', email: 'fallback.user@gmail.com', role: 'standard-user' },
] : [] },
};
}
if (/\/subscriptions\?/.test(path)) {
return { ok: true, status: 200, data: { seat_capacity: [{ available: 1 }] } };
}
if (/\/invites$/.test(path)) return { ok: true, status: 201, data: {} };
if (/\/invites\/accept$/.test(path)) {
if (options.token === fallbackOldToken) return { ok: false, status: 401, data: {} };
fallbackAccepted = true;
return { ok: true, status: 200, data: {} };
}
if (path === '/accounts/transfer') {
fallbackTransferAccountIds.push(options.accountId == null ? null : options.accountId);
return options.accountId === 'personal-fallback'
? { ok: true, status: 200, data: {} }
: { ok: false, status: 401, data: { error: { code: 'invalid_workspace_selected' } } };
}
if (/\/users\//.test(path) && options.method === 'DELETE') {
return { ok: true, status: 204, data: {} };
}
return { ok: true, status: 200, data: { users: [] } };
},
},
credentialRequester: {
async request(url) {
assert.match(url, /\/api\/auth\/session\?refresh=true/);
return {
ok: true,
status: 200,
data: {
user: { email: 'fallback.user@gmail.com' },
accessToken: fallbackNewToken,
expires: new Date(Date.now() + 7200000).toISOString(),
},
};
},
},
sleep: async () => {},
onUserCredentialsUpdated: async updated => fallbackUpdates.push(updated),
});
assert.strictEqual(fallbackResult.success, true, '退款没有授权 JSON 时仍应使用 sessionToken');
assert.strictEqual(fallbackUpdates.length, 1);
assert.strictEqual(JSON.parse(fallbackUpdates[0].sessionText).accessToken, fallbackNewToken);
assert.strictEqual(JSON.parse(fallbackUpdates[0].sessionText).sessionToken, 'fallback-session-token');
assert.deepStrictEqual(fallbackTransferAccountIds, ['team-001', 'personal-fallback'],
'迁移使用母号工作区返回 401 后,应改用目标账号原个人工作区重试');
assert.strictEqual(
refundPrivate.safeResponseMessage({ error: { code: 'invalid_workspace_selected' } }),
'{"error":{"code":"invalid_workspace_selected"}}',
'嵌套接口错误必须展开为可读 JSON,不能显示 [object Object]',
);
assert.strictEqual(refundPrivate.isAccessTokenExpired(fallbackOldToken), true);
assert.strictEqual(refundPrivate.isAccessTokenExpired(fallbackNewToken), false);
assert.strictEqual(
refundPrivate.shouldRefreshAccessToken(
{ status: 401, data: { error: { code: 'invalid_workspace_selected' } }, message: 'invalid workspace' },
fallbackNewToken,
),
false,
'有效 Token 遇到工作区 401 时不得错误触发凭据降级',
);
assert.strictEqual(
refundPrivate.shouldRefreshAccessToken(
{ status: 401, data: { code: 'token_expired' }, message: 'token expired' },
fallbackNewToken,
),
true,
'只有明确的 Token 失效错误才应触发凭据刷新',
);
assert.strictEqual(
refundPrivate.inviteFailureMessage({
account_invites: [],
errored_emails: [{
email_address: 'Fiorelli.Vlach@gmail.com',
error: 'Unable to invite user due to an error.',
}],
}, 'fiorellivlach@gmail.com'),
'Unable to invite user due to an error.',
'邀请接口 HTTP 200 时仍必须识别 Gmail 点号规则下的单邮箱业务失败',
);
let mismatchCalls = 0;
await assert.rejects(
executeWorkspaceRefund({
adminAccessToken: adminToken,
userSessionText: session,
expectedEmail: 'someone-else@gmail.com',
fetchImpl: async () => { mismatchCalls++; return response(500); },
sleep: async () => {},
}),
error => error && error.code === 'REFUND_SESSION_ACCOUNT_MISMATCH',
);
assert.strictEqual(mismatchCalls, 0, 'Session 邮箱不一致时不得发送任何外部请求');
const expiredAdmin = makeToken({
email: 'owner@gmail.com',
userId: 'owner-user',
accountId: 'team-001',
exp: Math.floor(Date.now() / 1000) - 10,
});
assert.throws(() => tokenInfo(expiredAdmin), error => error.code === 'REFUND_ADMIN_TOKEN_EXPIRED');
assert.strictEqual(
safeWorkspaceRefundFailure({ code: 'REFUND_TRANSFER_FAILED' }).message,
'去除个人空间失败',
);
assert.strictEqual(
safeWorkspaceRefundFailure({
code: 'REFUND_INVITE_FAILED',
message: '邀请目标账号失败(HTTP 400):unsupported seat type',
}).message,
'邀请目标账号失败(HTTP 400):unsupported seat type',
);
assert.strictEqual(
safeWorkspaceRefundFailure({ code: 'REFUND_CLOUDFLARE_BLOCKED' }).message,
'退款接口被 Cloudflare 拦截(HTTP 403)',
);
console.log('workspace_refund_service.test.js: PASS');
})().catch(error => {
console.error(error);
process.exitCode = 1;
});