You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
3.9 KiB
TypeScript
132 lines
3.9 KiB
TypeScript
import { OpenGroupData, OpenGroupV2Room } from '../../../../data/opengroups';
|
|
import _, { compact } from 'lodash';
|
|
import { OpenGroupMessageV2 } from './OpenGroupMessageV2';
|
|
import { UserUtils } from '../../../utils';
|
|
import { fromHexToArray } from '../../../utils/String';
|
|
import { getSodiumRenderer } from '../../../crypto';
|
|
import { SogsBlinding } from '../sogsv3/sogsBlinding';
|
|
import { getNowWithNetworkOffset } from '../../snode_api/SNodeAPI';
|
|
|
|
export type OpenGroupRequestHeaders = {
|
|
'X-SOGS-Pubkey': string;
|
|
'X-SOGS-Timestamp': string | number;
|
|
'X-SOGS-Signature': string;
|
|
'X-SOGS-Nonce': string;
|
|
/** content-type required for batch requests */
|
|
'Content-Type'?: string;
|
|
};
|
|
|
|
/**
|
|
* Creates headers for an authenticated open group request using our information
|
|
* @param serverPublicKey Public key of server we're requesting to
|
|
* @param endpoint endpoint of request we're making
|
|
* @param method method of request we're making
|
|
* @param blinded is the server being requested to blinded or not
|
|
* @param body the body of the request we're making
|
|
* @returns object of headers, including X-SOGS and other headers.
|
|
*/
|
|
const getOurOpenGroupHeaders = async (
|
|
serverPublicKey: string,
|
|
endpoint: string,
|
|
method: string,
|
|
blinded: boolean,
|
|
body: string | null | Uint8Array
|
|
): Promise<OpenGroupRequestHeaders | undefined> => {
|
|
// this value is cached
|
|
const signingKeys = await UserUtils.getUserED25519KeyPairBytes();
|
|
if (!signingKeys) {
|
|
window?.log?.error('getOurOpenGroupHeaders - Unable to get our signing keys');
|
|
return;
|
|
}
|
|
|
|
const nonce = (await getSodiumRenderer()).randombytes_buf(16);
|
|
|
|
const timestamp = Math.floor(getNowWithNetworkOffset() / 1000);
|
|
return SogsBlinding.getOpenGroupHeaders({
|
|
signingKeys,
|
|
serverPK: fromHexToArray(serverPublicKey),
|
|
nonce,
|
|
method,
|
|
path: endpoint,
|
|
timestamp,
|
|
blinded,
|
|
body,
|
|
});
|
|
};
|
|
|
|
/**
|
|
* This function fetches the valid roomInfos from the database.
|
|
* It also makes sure that the pubkey for all those rooms are the same, or returns null.
|
|
*/
|
|
const getAllValidRoomInfos = (
|
|
serverUrl: string,
|
|
rooms: Set<string>
|
|
): Array<OpenGroupV2Room> | null => {
|
|
const allServerPubKeys: Array<string> = [];
|
|
|
|
// fetch all the roomInfos for the specified rooms.
|
|
// those invalid (like, not found in db) are excluded (with lodash compact)
|
|
const validRoomInfos = compact(
|
|
[...rooms].map(roomId => {
|
|
try {
|
|
const fetchedInfo = OpenGroupData.getV2OpenGroupRoomByRoomId({
|
|
serverUrl,
|
|
roomId,
|
|
});
|
|
if (!fetchedInfo) {
|
|
window?.log?.warn('Could not find this room getMessages');
|
|
return null;
|
|
}
|
|
allServerPubKeys.push(fetchedInfo.serverPublicKey);
|
|
|
|
return fetchedInfo;
|
|
} catch (e) {
|
|
window?.log?.warn('failed to fetch roominfos for room', roomId);
|
|
return null;
|
|
}
|
|
})
|
|
);
|
|
if (!validRoomInfos?.length) {
|
|
return null;
|
|
}
|
|
// double check that all those server pubkeys are the same
|
|
let firstPubkey: string;
|
|
if (allServerPubKeys?.length) {
|
|
firstPubkey = allServerPubKeys[0];
|
|
const allMatch = allServerPubKeys.every(p => p === firstPubkey);
|
|
if (!allMatch) {
|
|
window?.log?.warn('All pubkeys do not match:', allServerPubKeys);
|
|
return null;
|
|
}
|
|
} else {
|
|
window?.log?.warn('No pubkeys found:', allServerPubKeys);
|
|
return null;
|
|
}
|
|
return validRoomInfos;
|
|
};
|
|
|
|
export type ParsedDeletions = Array<{ id: number; deleted_message_id: number }>;
|
|
|
|
type StatusCodeType = {
|
|
statusCode: number;
|
|
};
|
|
|
|
export type ParsedRoomCompactPollResults = StatusCodeType & {
|
|
roomId: string;
|
|
deletions: ParsedDeletions;
|
|
messages: Array<OpenGroupMessageV2>;
|
|
moderators: Array<string>;
|
|
};
|
|
|
|
export type ParsedBase64Avatar = {
|
|
roomId: string;
|
|
base64: string;
|
|
};
|
|
|
|
export type ParsedMemberCount = {
|
|
roomId: string;
|
|
memberCount: number;
|
|
};
|
|
|
|
export const OpenGroupPollingUtils = { getAllValidRoomInfos, getOurOpenGroupHeaders };
|