mirror of
https://github.com/signalapp/libsignal.git
synced 2026-04-26 01:35:22 +02:00
This allows the file to be checked by tsc, which would have caught some of the missing type aliases sooner (now added to Native.ts.in). Strictly speaking the behavior is slightly different: we have returned to exporting many items individually instead of collecting them on a single object. Co-authored-by: Alex Bakon <akonradi@signal.org>
189 lines
5.5 KiB
TypeScript
189 lines
5.5 KiB
TypeScript
//
|
|
// Copyright 2025 Signal Messenger, LLC.
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import { assert, config, expect, use } from 'chai';
|
|
import chaiAsPromised from 'chai-as-promised';
|
|
import { Buffer } from 'node:buffer';
|
|
|
|
import * as Native from '../../Native.js';
|
|
import * as util from '../util.js';
|
|
import { TokioAsyncContext, UnauthUsernamesService } from '../../net.js';
|
|
import { connectUnauth } from './ServiceTestUtils.js';
|
|
import { InternalRequest } from '../NetTest.js';
|
|
import { newNativeHandle } from '../../internal.js';
|
|
import { ErrorCode, LibSignalErrorBase } from '../../Errors.js';
|
|
import { Aci } from '../../Address.js';
|
|
|
|
use(chaiAsPromised);
|
|
|
|
util.initLogger();
|
|
config.truncateThreshold = 0;
|
|
|
|
describe('UnauthUsernamesService', () => {
|
|
it('can look up hashes', async () => {
|
|
const tokio = new TokioAsyncContext(Native.TokioAsyncContext_new());
|
|
const [chat, fakeRemote] = connectUnauth<UnauthUsernamesService>(tokio);
|
|
|
|
const hash = Uint8Array.of(1, 2, 3, 4);
|
|
const responseFuture = chat.lookUpUsernameHash({ hash });
|
|
|
|
const rawRequest =
|
|
await Native.TESTING_FakeChatRemoteEnd_ReceiveIncomingRequest(
|
|
tokio,
|
|
fakeRemote
|
|
);
|
|
assert(rawRequest !== null);
|
|
const request = new InternalRequest(rawRequest);
|
|
expect(request.verb).to.eq('GET');
|
|
expect(request.path).to.eq(
|
|
`/v1/accounts/username_hash/${Buffer.from(hash).toString('base64url')}`
|
|
);
|
|
|
|
const uuid = '4fcfe887-a600-40cd-9ab7-fd2a695e9981';
|
|
|
|
Native.TESTING_FakeChatRemoteEnd_SendServerResponse(
|
|
fakeRemote,
|
|
newNativeHandle(
|
|
Native.TESTING_FakeChatResponse_Create(
|
|
request.requestId,
|
|
200,
|
|
'OK',
|
|
['content-type: application/json'],
|
|
Buffer.from(
|
|
JSON.stringify({
|
|
uuid,
|
|
})
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
const responseFromServer = await responseFuture;
|
|
assert(responseFromServer !== null);
|
|
assert(Aci.fromUuid(uuid).isEqual(responseFromServer));
|
|
});
|
|
|
|
it('can look up unknown hashes', async () => {
|
|
const tokio = new TokioAsyncContext(Native.TokioAsyncContext_new());
|
|
const [chat, fakeRemote] = connectUnauth<UnauthUsernamesService>(tokio);
|
|
|
|
const hash = Uint8Array.of(1, 2, 3, 4);
|
|
const responseFuture = chat.lookUpUsernameHash({ hash });
|
|
|
|
const rawRequest =
|
|
await Native.TESTING_FakeChatRemoteEnd_ReceiveIncomingRequest(
|
|
tokio,
|
|
fakeRemote
|
|
);
|
|
assert(rawRequest !== null);
|
|
const request = new InternalRequest(rawRequest);
|
|
expect(request.verb).to.eq('GET');
|
|
expect(request.path).to.eq(
|
|
`/v1/accounts/username_hash/${Buffer.from(hash).toString('base64url')}`
|
|
);
|
|
|
|
Native.TESTING_FakeChatRemoteEnd_SendServerResponse(
|
|
fakeRemote,
|
|
newNativeHandle(
|
|
Native.TESTING_FakeChatResponse_Create(
|
|
request.requestId,
|
|
404,
|
|
'Not Found',
|
|
[],
|
|
Buffer.of()
|
|
)
|
|
)
|
|
);
|
|
|
|
const responseFromServer = await responseFuture;
|
|
assert.isNull(responseFromServer);
|
|
});
|
|
|
|
it('can handle challenge errors', async () => {
|
|
const tokio = new TokioAsyncContext(Native.TokioAsyncContext_new());
|
|
const [chat, fakeRemote] = connectUnauth<UnauthUsernamesService>(tokio);
|
|
|
|
const hash = Uint8Array.of(1, 2, 3, 4);
|
|
const responseFuture = chat.lookUpUsernameHash({ hash });
|
|
|
|
const rawRequest =
|
|
await Native.TESTING_FakeChatRemoteEnd_ReceiveIncomingRequest(
|
|
tokio,
|
|
fakeRemote
|
|
);
|
|
assert(rawRequest !== null);
|
|
const request = new InternalRequest(rawRequest);
|
|
expect(request.verb).to.eq('GET');
|
|
expect(request.path).to.eq(
|
|
`/v1/accounts/username_hash/${Buffer.from(hash).toString('base64url')}`
|
|
);
|
|
|
|
Native.TESTING_FakeChatRemoteEnd_SendServerResponse(
|
|
fakeRemote,
|
|
newNativeHandle(
|
|
Native.TESTING_FakeChatResponse_Create(
|
|
request.requestId,
|
|
428,
|
|
'Precondition Required',
|
|
['content-type: application/json'],
|
|
Buffer.from(
|
|
JSON.stringify({
|
|
token: 'not-legal-tender',
|
|
options: ['pushChallenge'],
|
|
})
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
await expect(responseFuture)
|
|
.to.eventually.be.rejectedWith(LibSignalErrorBase)
|
|
.and.deep.include({
|
|
code: ErrorCode.RateLimitChallengeError,
|
|
token: 'not-legal-tender',
|
|
options: new Set(['pushChallenge']),
|
|
});
|
|
});
|
|
|
|
it('can handle server errors', async () => {
|
|
const tokio = new TokioAsyncContext(Native.TokioAsyncContext_new());
|
|
const [chat, fakeRemote] = connectUnauth<UnauthUsernamesService>(tokio);
|
|
|
|
const hash = Uint8Array.of(1, 2, 3, 4);
|
|
const responseFuture = chat.lookUpUsernameHash({ hash });
|
|
|
|
const rawRequest =
|
|
await Native.TESTING_FakeChatRemoteEnd_ReceiveIncomingRequest(
|
|
tokio,
|
|
fakeRemote
|
|
);
|
|
assert(rawRequest !== null);
|
|
const request = new InternalRequest(rawRequest);
|
|
expect(request.verb).to.eq('GET');
|
|
expect(request.path).to.eq(
|
|
`/v1/accounts/username_hash/${Buffer.from(hash).toString('base64url')}`
|
|
);
|
|
|
|
Native.TESTING_FakeChatRemoteEnd_SendServerResponse(
|
|
fakeRemote,
|
|
newNativeHandle(
|
|
Native.TESTING_FakeChatResponse_Create(
|
|
request.requestId,
|
|
500,
|
|
'Internal Server Error',
|
|
[],
|
|
Buffer.of()
|
|
)
|
|
)
|
|
);
|
|
|
|
await expect(responseFuture)
|
|
.to.eventually.be.rejectedWith(LibSignalErrorBase)
|
|
.and.deep.include({
|
|
code: ErrorCode.IoError,
|
|
});
|
|
});
|
|
});
|