feat:昵称重复、显示分销人分销tree
This commit is contained in:
1 parent
4518856ccd
commit
074307b07b
50 files changed
+3386
-116
No files matched your search
@@ -0,0 +1,109 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { createHash } from 'node:crypto';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
|
||||
const endpoint = process.env.CHAT_SYNC_RUNTIME_HTTP;
|
||||
const socketEndpoint = process.env.CHAT_SYNC_RUNTIME_SOCKET;
|
||||
const secondSocketEndpoint = process.env.CHAT_SYNC_RUNTIME_SOCKET_SECOND;
|
||||
|
||||
test('local HTTP and WebSocket enforce disable, restore and credential revocation', {
|
||||
skip: !endpoint || !socketEndpoint,
|
||||
timeout: 30000,
|
||||
}, async () => {
|
||||
assert.match(endpoint, /^http:\/\/(127\.0\.0\.1|localhost):[0-9]+$/);
|
||||
assert.match(socketEndpoint, /^ws:\/\/(127\.0\.0\.1|localhost):[0-9]+$/);
|
||||
assert.equal(typeof WebSocket, 'function', 'Node 20 requires --experimental-websocket');
|
||||
const source = await readFile(new URL('../../../../Friendship-and-chat-im/box-im-master/im-platform/src/main/java/com/bx/implatform/enums/third/ThirdKeyTypeEnum.java', import.meta.url), 'utf8');
|
||||
const match = source.match(/\(\s*"10"\s*,\s*"[^"]*"\s*,\s*"([^"]+)"\s*,\s*"([^"]+)"\s*\)/);
|
||||
assert.ok(match, 'Fixture signing configuration must be available locally');
|
||||
const [, key, secret] = match;
|
||||
|
||||
async function third(path, data) {
|
||||
const body = JSON.stringify(data);
|
||||
const timestamp = String(Math.floor(Date.now() / 1000));
|
||||
const sign = createHash('md5').update(key + secret + '10' + timestamp + body).digest('hex');
|
||||
const response = await fetch(endpoint + path, { method: 'POST', body,
|
||||
headers: { 'Content-Type': 'application/json', 'APP-KEY': key, 'BIZ-TYPE': '10', TIMESTAMP: timestamp, SIGN: sign } });
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async function connect(token, target = socketEndpoint) {
|
||||
assert.match(target, /^ws:\/\/(127\.0\.0\.1|localhost):[0-9]+$/);
|
||||
const socket = new WebSocket(new URL('/im', target));
|
||||
const packets = [];
|
||||
let notify;
|
||||
const first = new Promise(resolve => { notify = resolve; });
|
||||
socket.addEventListener('message', message => {
|
||||
const packet = JSON.parse(message.data);
|
||||
packets.push(packet);
|
||||
notify(packet);
|
||||
});
|
||||
const closed = new Promise(resolve => socket.addEventListener('close', resolve));
|
||||
await new Promise((resolve, reject) => {
|
||||
socket.addEventListener('open', resolve, { once: true });
|
||||
socket.addEventListener('error', reject, { once: true });
|
||||
});
|
||||
socket.send(JSON.stringify({ cmd: 0, data: { accessToken: token } }));
|
||||
return { socket, packets, first, closed };
|
||||
}
|
||||
|
||||
const current = await third('/third/user/getUserByUserId', { userId: 131 });
|
||||
const version = Number(current.data?.syncVersion ?? 0) + 1;
|
||||
const profile = { userId: 131, userName: '老芋头', nickName: '老芋头', avatar: '', memberState: 0, syncVersion: version };
|
||||
const synchronized = await third('/third/user/createOrUpdate', profile);
|
||||
assert.equal(synchronized.code, 200, synchronized.message);
|
||||
assert.equal(synchronized.data.appliedVersion, version);
|
||||
const initial = await third('/third/user/login', { userId: 131, terminal: 1 });
|
||||
assert.equal(initial.code, 200);
|
||||
const old = await connect(initial.data.accessToken);
|
||||
const otherNode = secondSocketEndpoint ? await connect(initial.data.accessToken, secondSocketEndpoint) : null;
|
||||
try {
|
||||
assert.equal((await old.first).cmd, 0);
|
||||
if (otherNode) assert.equal((await otherNode.first).cmd, 0);
|
||||
assert.equal((await third('/third/user/createOrUpdate', { ...profile, memberState: 1, syncVersion: version + 1 })).code, 200);
|
||||
await old.closed;
|
||||
if (otherNode) await otherNode.closed;
|
||||
assert.ok(old.packets.some(packet => packet.cmd === 2 && packet.data.includes('禁用')));
|
||||
const blocked = await fetch(endpoint + '/user/self', { headers: { accessToken: initial.data.accessToken } }).then(response => response.json());
|
||||
assert.equal(blocked.code, 10005);
|
||||
const refresh = await fetch(endpoint + '/refreshToken', { method: 'PUT', headers: { refreshToken: initial.data.refreshToken } }).then(response => response.json());
|
||||
assert.equal(refresh.code, 10005);
|
||||
assert.equal((await third('/third/user/createOrUpdate', { ...profile, syncVersion: version + 2 })).code, 200);
|
||||
const restored = await third('/third/user/login', { userId: 131, terminal: 1 });
|
||||
assert.equal(restored.code, 200);
|
||||
assert.notEqual(restored.data.accessToken, initial.data.accessToken);
|
||||
const stale = await connect(initial.data.accessToken);
|
||||
assert.equal((await stale.first).cmd, 2);
|
||||
await stale.closed;
|
||||
const fresh = await connect(restored.data.accessToken);
|
||||
try {
|
||||
assert.equal((await fresh.first).cmd, 0);
|
||||
const revoked = await fetch(endpoint + '/user/self', { headers: { accessToken: initial.data.accessToken } }).then(response => response.json());
|
||||
assert.equal(revoked.code, 401);
|
||||
const active = await fetch(endpoint + '/user/self', { headers: { accessToken: restored.data.accessToken } }).then(response => response.json());
|
||||
assert.equal(active.code, 200);
|
||||
assert.equal(active.data.userName, 'u131');
|
||||
const independent = await fetch(endpoint + '/login', { method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ userName: 'testuser', password: 'Password123', terminal: 1 }) }).then(response => response.json());
|
||||
assert.equal(independent.code, 10007);
|
||||
const missedTransition = await third('/third/user/createOrUpdate', {
|
||||
...profile, syncVersion: version + 4, accessChangeVersion: version + 4,
|
||||
});
|
||||
assert.equal(missedTransition.code, 200);
|
||||
const revokedAfterMissedDisable = await fetch(endpoint + '/user/self', {
|
||||
headers: { accessToken: restored.data.accessToken },
|
||||
}).then(response => response.json());
|
||||
assert.equal(revokedAfterMissedDisable.code, 401);
|
||||
fresh.socket.send(JSON.stringify({ cmd: 1, data: {} }));
|
||||
await fresh.closed;
|
||||
assert.ok(fresh.packets.some(packet => packet.cmd === 2));
|
||||
} finally {
|
||||
fresh.socket.close();
|
||||
}
|
||||
} finally {
|
||||
old.socket.close();
|
||||
otherNode?.socket.close();
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user