add getMessages and postMessages OpenGroupAPIV2

pull/1576/head
Audric Ackermann 4 years ago
parent b68338e26c
commit b73685008c
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -3,8 +3,6 @@ import { SessionIconButton, SessionIconSize, SessionIconType } from './icon';
import { Avatar } from '../Avatar';
import { darkTheme, lightTheme } from '../../state/ducks/SessionTheme';
import { SessionToastContainer } from './SessionToastContainer';
import { ConversationType } from '../../state/ducks/conversations';
import { DefaultTheme } from 'styled-components';
import { ConversationController } from '../../session/conversations';
import { UserUtils } from '../../session/utils';
import { syncConfigurationIfNeeded } from '../../session/utils/syncUtils';
@ -35,8 +33,11 @@ import {
} from '../../opengroup/opengroupV2/JoinOpenGroupV2';
import {
getAuthToken,
getMessages,
getModerators,
postMessage,
} from '../../opengroup/opengroupV2/OpenGroupAPIV2';
import { OpenGroupMessageV2 } from '../../opengroup/opengroupV2/OpenGroupMessageV2';
// tslint:disable-next-line: no-import-side-effect no-submodule-imports
export enum SectionType {
@ -193,7 +194,19 @@ export const ActionsPanel = () => {
if (parsedRoom) {
setTimeout(async () => {
await joinOpenGroupV2(parsedRoom);
await getModerators({
const oldMessages = await getMessages({
serverUrl: parsedRoom.serverUrl,
roomId: parsedRoom.roomId,
});
const msg = new OpenGroupMessageV2({
base64EncodedData: 'dffdldfkldf',
sentTimestamp: Date.now(),
});
const postedMessage = await postMessage(msg, {
serverUrl: parsedRoom.serverUrl,
roomId: parsedRoom.roomId,
});
const newMessages = await getMessages({
serverUrl: parsedRoom.serverUrl,
roomId: parsedRoom.roomId,
});

@ -1,3 +1,4 @@
import { OpenGroupRequestCommonType } from '../opengroup/opengroupV2/ApiUtil';
import { channels } from './channels';
export type OpenGroupV2Room = {
@ -47,10 +48,9 @@ export async function getV2OpenGroupRoom(
return opengroupv2Rooms;
}
export async function getV2OpenGroupRoomByRoomId(roomInfos: {
serverUrl: string;
roomId: string;
}): Promise<OpenGroupV2Room | undefined> {
export async function getV2OpenGroupRoomByRoomId(
roomInfos: OpenGroupRequestCommonType
): Promise<OpenGroupV2Room | undefined> {
console.warn('getting roomInfo', roomInfos);
const room = await channels.getV2OpenGroupRoomByRoomId(
roomInfos.serverUrl,

@ -1,7 +1,23 @@
import _ from 'underscore';
import { getSodium } from '../../session/crypto';
import { PubKey } from '../../session/types';
import {
fromBase64ToArray,
fromBase64ToArrayBuffer,
fromHex,
fromHexToArray,
} from '../../session/utils/String';
import { OpenGroupMessageV2 } from './OpenGroupMessageV2';
export const defaultServer = 'https://sessionopengroup.com';
export const defaultServerPublicKey =
'658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231b';
export type OpenGroupRequestCommonType = {
serverUrl: string;
roomId: string;
};
export type OpenGroupV2Request = {
method: 'GET' | 'POST' | 'DELETE' | 'PUT';
room: string;
@ -70,3 +86,49 @@ export const setCachedModerators = (
allRoomsMods!.get(roomId)?.add(m);
});
};
export const parseMessages = async (
rawMessages: Array<Record<string, any>>
): Promise<Array<OpenGroupMessageV2>> => {
const messages = await Promise.all(
rawMessages.map(async r => {
try {
const opengroupMessage = OpenGroupMessageV2.fromJson(r);
console.warn('opengroupMessage', opengroupMessage);
if (
!opengroupMessage?.serverId ||
!opengroupMessage.sentTimestamp ||
!opengroupMessage.base64EncodedData ||
!opengroupMessage.base64EncodedSignature
) {
window.log.warn('invalid open group message received');
return null;
}
// Validate the message signature
const senderPubKey = PubKey.cast(
opengroupMessage.sender
).withoutPrefix();
const signature = fromBase64ToArrayBuffer(
opengroupMessage.base64EncodedSignature
);
const messageData = fromBase64ToArrayBuffer(
opengroupMessage.base64EncodedData
);
// throws if signature failed
await window.libsignal.Curve.async.verifySignature(
fromHex(senderPubKey),
messageData,
signature
);
return opengroupMessage;
} catch (e) {
window.log.error(
'An error happened while fetching getMessages output:',
e
);
return null;
}
})
);
return _.compact(messages);
};

@ -1,10 +1,18 @@
import _ from 'lodash';
import {
getV2OpenGroupRoomByRoomId,
saveV2OpenGroupRoom,
} from '../../data/opengroups';
import { getSodium } from '../../session/crypto';
import { sendViaOnion } from '../../session/onions/onionSend';
import { PubKey } from '../../session/types';
import { allowOnlyOneAtATime } from '../../session/utils/Promise';
import { fromBase64ToArrayBuffer, toHex } from '../../session/utils/String';
import {
fromBase64ToArray,
fromBase64ToArrayBuffer,
fromHexToArray,
toHex,
} from '../../session/utils/String';
import {
getIdentityKeyPair,
getOurPubKeyStrFromCache,
@ -12,10 +20,13 @@ import {
import {
buildUrl,
cachedModerators,
OpenGroupRequestCommonType,
OpenGroupV2Info,
OpenGroupV2Request,
parseMessages,
setCachedModerators,
} from './ApiUtil';
import { OpenGroupMessageV2 } from './OpenGroupMessageV2';
// This function might throw
async function sendOpenGroupV2Request(
@ -89,10 +100,7 @@ async function sendOpenGroupV2Request(
export async function requestNewAuthToken({
serverUrl,
roomId,
}: {
serverUrl: string;
roomId: string;
}): Promise<string> {
}: OpenGroupRequestCommonType): Promise<string> {
const userKeyPair = await getIdentityKeyPair();
if (!userKeyPair) {
throw new Error('Failed to fetch user keypair');
@ -211,10 +219,7 @@ async function claimAuthToken(
export async function getAuthToken({
serverUrl,
roomId,
}: {
serverUrl: string;
roomId: string;
}): Promise<string> {
}: OpenGroupRequestCommonType): Promise<string> {
// first try to fetch from db a saved token.
const roomDetails = await getV2OpenGroupRoomByRoomId({ serverUrl, roomId });
if (!roomDetails) {
@ -246,10 +251,7 @@ export async function getAuthToken({
export const getModerators = async ({
serverUrl,
roomId,
}: {
serverUrl: string;
roomId: string;
}): Promise<Array<string>> => {
}: OpenGroupRequestCommonType): Promise<Array<string>> => {
const request: OpenGroupV2Request = {
method: 'GET',
room: roomId,
@ -276,10 +278,7 @@ export const getModerators = async ({
export const deleteAuthToken = async ({
serverUrl,
roomId,
}: {
serverUrl: string;
roomId: string;
}) => {
}: OpenGroupRequestCommonType) => {
const request: OpenGroupV2Request = {
method: 'DELETE',
room: roomId,
@ -298,21 +297,74 @@ export const deleteAuthToken = async ({
export const getMessages = async ({
serverUrl,
roomId,
}: {
serverUrl: string;
roomId: string;
}) => {
}: OpenGroupRequestCommonType): Promise<Array<OpenGroupMessageV2>> => {
const roomInfos = await getV2OpenGroupRoomByRoomId({ serverUrl, roomId });
if (!roomInfos) {
throw new Error('Could not find this room getMessages');
}
const { lastMessageFetchedServerID } = roomInfos;
const queryParams = {} as Record<string, any>;
if (lastMessageFetchedServerID) {
queryParams.from_server_id = lastMessageFetchedServerID;
}
const request: OpenGroupV2Request = {
method: 'GET',
room: roomId,
server: serverUrl,
isAuthRequired: false,
endpoint: 'auth_token',
isAuthRequired: true,
endpoint: 'messages',
};
const result = (await sendOpenGroupV2Request(request)) as any;
if (result?.result?.status_code !== 200) {
throw new Error(
`Could not deleteAuthToken, status code: ${result?.result?.status_code}`
`Could not getMessages, status code: ${result?.result?.status_code}`
);
}
// we have a 200
const rawMessages = result?.result?.messages as Array<Record<string, any>>;
if (!rawMessages) {
window.log.info('no new messages');
return [];
}
const validMessages = await parseMessages(rawMessages);
console.warn('validMessages', validMessages);
return validMessages;
};
export const postMessage = async (
message: OpenGroupMessageV2,
room: OpenGroupRequestCommonType
) => {
try {
const signedMessage = await message.sign();
const json = signedMessage.toJson();
console.warn('posting message json', json);
const request: OpenGroupV2Request = {
method: 'POST',
room: room.roomId,
server: room.serverUrl,
queryParams: json,
isAuthRequired: true,
endpoint: 'messages',
};
const result = (await sendOpenGroupV2Request(request)) as any;
if (result?.result?.status_code !== 200) {
throw new Error(
`Could not postMessage, status code: ${result?.result?.status_code}`
);
}
const rawMessage = result?.result?.message;
if (!rawMessage) {
throw new Error('postMessage parsing failed');
}
// this will throw if the json is not valid
return OpenGroupMessageV2.fromJson(rawMessage);
} catch (e) {
window.log.error('Failed to post message to open group v2', e);
throw e;
}
};

@ -1,6 +1,7 @@
import { getSodium } from '../../session/crypto';
import { UserUtils } from '../../session/utils';
import {
fromArrayBufferToBase64,
fromBase64ToArray,
fromHex,
fromHexToArray,
@ -36,17 +37,39 @@ export class OpenGroupMessageV2 {
this.serverId = serverId;
}
public async sign() {
const ourKeyPair = await UserUtils.getUserED25519KeyPair();
public static fromJson(json: Record<string, any>) {
const {
data: base64EncodedData,
timestamp: sentTimestamp,
server_id: serverId,
public_key: sender,
signature: base64EncodedSignature,
} = json;
if (!base64EncodedData || !sentTimestamp) {
window.log.info('invalid json to build OpenGroupMessageV2');
throw new Error('OpengroupV2Message fromJson() failed');
}
return new OpenGroupMessageV2({
base64EncodedData,
base64EncodedSignature,
sentTimestamp,
serverId,
sender,
});
}
public async sign(): Promise<OpenGroupMessageV2> {
const ourKeyPair = await UserUtils.getIdentityKeyPair();
if (!ourKeyPair) {
window.log.warn("Couldn't find user X25519 key pair.");
return null;
throw new Error("Couldn't sign message");
}
const data = fromBase64ToArray(this.base64EncodedData);
const sodium = await getSodium();
const signature = sodium.crypto_sign_detached(
data,
fromHexToArray(ourKeyPair.privKey)
const signature = await window.libsignal.Curve.async.calculateSignature(
ourKeyPair.privKey,
data.buffer
);
if (!signature || signature.length === 0) {
throw new Error("Couldn't sign message");
@ -54,7 +77,7 @@ export class OpenGroupMessageV2 {
return new OpenGroupMessageV2({
base64EncodedData: this.base64EncodedData,
sentTimestamp: this.sentTimestamp,
base64EncodedSignature: toHex(signature),
base64EncodedSignature: fromArrayBufferToBase64(signature),
sender: this.sender,
serverId: this.serverId,
});
@ -74,27 +97,6 @@ export class OpenGroupMessageV2 {
if (this.base64EncodedSignature) {
json.signature = this.base64EncodedSignature;
}
}
public fromJson(json: Record<string, any>) {
const {
data: base64EncodedData,
timestamp: sentTimestamp,
server_id: serverId,
public_key: sender,
signature: base64EncodedSignature,
} = json;
if (!base64EncodedData || !sentTimestamp) {
window.log.info('invalid json to build OpenGroupMessageV2');
return null;
}
return new OpenGroupMessageV2({
base64EncodedData,
base64EncodedSignature,
sentTimestamp,
serverId,
sender,
});
return json;
}
}

Loading…
Cancel
Save