add contacts to ConfigurationMessage
This commit is contained in:
parent
0a82bf98fa
commit
a61f5e6814
|
@ -23,6 +23,7 @@ interface ConversationAttributes {
|
|||
type: string;
|
||||
lastMessage?: string;
|
||||
avatarPointer?: string;
|
||||
profileKey?: Uint8Array;
|
||||
}
|
||||
|
||||
export interface ConversationModel
|
||||
|
|
|
@ -1297,12 +1297,17 @@
|
|||
(dataMessage.body && dataMessage.body.length) ||
|
||||
dataMessage.attachments.length
|
||||
) {
|
||||
const syncMessage = libsession.Messages.Outgoing.ChatMessage.buildSyncMessage(
|
||||
dataMessage,
|
||||
this.getConversation().id,
|
||||
sentTimestamp
|
||||
);
|
||||
await libsession.getMessageQueue().sendSyncMessage(syncMessage);
|
||||
// try catch not to be kept
|
||||
try {
|
||||
const syncMessage = libsession.Messages.Outgoing.ChatMessage.buildSyncMessage(
|
||||
dataMessage,
|
||||
this.getConversation().id,
|
||||
sentTimestamp
|
||||
);
|
||||
await libsession.getMessageQueue().sendSyncMessage(syncMessage);
|
||||
} catch (e) {
|
||||
window.log.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
// - copy all fields from dataMessage and create a new ChatMessage
|
||||
|
|
|
@ -217,11 +217,19 @@ message ConfigurationMessage {
|
|||
repeated bytes admins = 5;
|
||||
}
|
||||
|
||||
message Contact {
|
||||
optional bytes publicKey = 1;
|
||||
optional string name = 2;
|
||||
optional string profilePicture = 3;
|
||||
optional bytes profileKey = 4;
|
||||
}
|
||||
|
||||
repeated ClosedGroup closedGroups = 1;
|
||||
repeated string openGroups = 2;
|
||||
optional string displayName = 3;
|
||||
optional string profilePicture = 4;
|
||||
optional bytes profileKey = 5;
|
||||
repeated Contact contacts = 6;
|
||||
}
|
||||
|
||||
message ReceiptMessage {
|
||||
|
|
|
@ -14,6 +14,7 @@ interface ConfigurationMessageParams extends MessageParams {
|
|||
displayName: string;
|
||||
profilePicture?: string;
|
||||
profileKey?: Uint8Array;
|
||||
contacts: Array<ConfigurationMessageContact>;
|
||||
}
|
||||
|
||||
export class ConfigurationMessage extends ContentMessage {
|
||||
|
@ -22,6 +23,7 @@ export class ConfigurationMessage extends ContentMessage {
|
|||
public readonly displayName: string;
|
||||
public readonly profilePicture?: string;
|
||||
public readonly profileKey?: Uint8Array;
|
||||
public readonly contacts: Array<ConfigurationMessageContact>;
|
||||
|
||||
constructor(params: ConfigurationMessageParams) {
|
||||
super({ timestamp: params.timestamp, identifier: params.identifier });
|
||||
|
@ -30,6 +32,7 @@ export class ConfigurationMessage extends ContentMessage {
|
|||
this.displayName = params.displayName;
|
||||
this.profilePicture = params.profilePicture;
|
||||
this.profileKey = params.profileKey;
|
||||
this.contacts = params.contacts;
|
||||
|
||||
if (!this.activeClosedGroups) {
|
||||
throw new Error('closed group must be set');
|
||||
|
@ -50,6 +53,10 @@ export class ConfigurationMessage extends ContentMessage {
|
|||
if (this.profileKey && !(this.profileKey instanceof Uint8Array)) {
|
||||
throw new Error('profileKey set but not an Uin8Array');
|
||||
}
|
||||
|
||||
if (!this.contacts) {
|
||||
throw new Error('contacts must be set');
|
||||
}
|
||||
}
|
||||
|
||||
public ttl(): number {
|
||||
|
@ -69,6 +76,7 @@ export class ConfigurationMessage extends ContentMessage {
|
|||
displayName: this.displayName,
|
||||
profilePicture: this.profilePicture,
|
||||
profileKey: this.profileKey,
|
||||
contacts: this.mapContactsObjectToProto(this.contacts),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -79,6 +87,64 @@ export class ConfigurationMessage extends ContentMessage {
|
|||
new ConfigurationMessageClosedGroup(m).toProto()
|
||||
);
|
||||
}
|
||||
|
||||
private mapContactsObjectToProto(
|
||||
contacts: Array<ConfigurationMessageContact>
|
||||
): Array<SignalService.ConfigurationMessage.Contact> {
|
||||
return (contacts || []).map(m =>
|
||||
new ConfigurationMessageContact(m).toProto()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class ConfigurationMessageContact {
|
||||
public publicKey: string;
|
||||
public displayName: string;
|
||||
public profilePictureURL?: string;
|
||||
public profileKey?: Uint8Array;
|
||||
|
||||
public constructor({
|
||||
publicKey,
|
||||
displayName,
|
||||
profilePictureURL,
|
||||
profileKey,
|
||||
}: {
|
||||
publicKey: string;
|
||||
displayName: string;
|
||||
profilePictureURL?: string;
|
||||
profileKey?: Uint8Array;
|
||||
}) {
|
||||
this.publicKey = publicKey;
|
||||
this.displayName = displayName;
|
||||
this.profilePictureURL = profilePictureURL;
|
||||
this.profileKey = profileKey;
|
||||
|
||||
// will throw if public key is invalid
|
||||
PubKey.cast(publicKey);
|
||||
|
||||
if (this.displayName?.length === 0) {
|
||||
throw new Error('displayName must be set or undefined');
|
||||
}
|
||||
|
||||
if (
|
||||
this.profilePictureURL !== undefined &&
|
||||
this.profilePictureURL?.length === 0
|
||||
) {
|
||||
throw new Error('profilePictureURL must either undefined or not empty');
|
||||
}
|
||||
if (this.profileKey !== undefined && this.profileKey?.length === 0) {
|
||||
throw new Error('profileKey must either undefined or not empty');
|
||||
}
|
||||
}
|
||||
|
||||
public toProto(): SignalService.ConfigurationMessage.Contact {
|
||||
return new SignalService.ConfigurationMessage.Contact({
|
||||
publicKey: fromHexToArray(this.publicKey),
|
||||
name: this.displayName,
|
||||
profilePicture: this.profilePictureURL,
|
||||
profileKey: this.profileKey,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class ConfigurationMessageClosedGroup {
|
||||
|
|
|
@ -10,6 +10,7 @@ import { ConversationModel } from '../../../js/models/conversations';
|
|||
import {
|
||||
ConfigurationMessage,
|
||||
ConfigurationMessageClosedGroup,
|
||||
ConfigurationMessageContact,
|
||||
} from '../messages/outgoing/content/ConfigurationMessage';
|
||||
import uuid from 'uuid';
|
||||
import { getLatestClosedGroupEncryptionKeyPair } from '../../../js/modules/data';
|
||||
|
@ -70,11 +71,15 @@ export const getCurrentConfigurationMessage = async (
|
|||
) => {
|
||||
const ourPubKey = (await UserUtils.getOurNumber()).key;
|
||||
const ourConvo = convos.find(convo => convo.id === ourPubKey);
|
||||
|
||||
// Filter open groups
|
||||
const openGroupsIds = convos
|
||||
.filter(c => !!c.get('active_at') && c.isPublic() && !c.get('left'))
|
||||
.map(c => c.id.substring((c.id as string).lastIndexOf('@') + 1)) as Array<
|
||||
string
|
||||
>;
|
||||
|
||||
// Filter Closed/Medium groups
|
||||
const closedGroupModels = convos.filter(
|
||||
c =>
|
||||
!!c.get('active_at') &&
|
||||
|
@ -109,6 +114,21 @@ export const getCurrentConfigurationMessage = async (
|
|||
ConfigurationMessageClosedGroup
|
||||
>;
|
||||
|
||||
// Filter contacts
|
||||
const contactsModels = convos.filter(
|
||||
c => !!c.get('active_at') && c.isPrivate() && !c.isBlocked()
|
||||
);
|
||||
|
||||
const contacts = contactsModels.map(c => {
|
||||
const groupPubKey = c.get('id');
|
||||
return new ConfigurationMessageContact({
|
||||
publicKey: groupPubKey,
|
||||
displayName: c.get('name'),
|
||||
profilePictureURL: c.get('avatarPointer'),
|
||||
profileKey: c.get('profileKey'),
|
||||
});
|
||||
});
|
||||
|
||||
if (!ourConvo) {
|
||||
window.log.error(
|
||||
'Could not find our convo while building a configuration message.'
|
||||
|
@ -130,5 +150,6 @@ export const getCurrentConfigurationMessage = async (
|
|||
displayName,
|
||||
profilePicture,
|
||||
profileKey,
|
||||
contacts,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -4,6 +4,7 @@ import { ECKeyPair } from '../../../../receiver/keypairs';
|
|||
import {
|
||||
ConfigurationMessage,
|
||||
ConfigurationMessageClosedGroup,
|
||||
ConfigurationMessageContact,
|
||||
} from '../../../../session/messages/outgoing/content/ConfigurationMessage';
|
||||
import { TestUtils } from '../../../test-utils';
|
||||
|
||||
|
@ -16,6 +17,7 @@ describe('ConfigurationMessage', () => {
|
|||
activeOpenGroups: [],
|
||||
timestamp: Date.now(),
|
||||
displayName: 'displayName',
|
||||
contacts: [],
|
||||
};
|
||||
expect(() => new ConfigurationMessage(params)).to.throw(
|
||||
'closed group must be set'
|
||||
|
@ -29,6 +31,7 @@ describe('ConfigurationMessage', () => {
|
|||
activeOpenGroups,
|
||||
timestamp: Date.now(),
|
||||
displayName: 'displayName',
|
||||
contacts: [],
|
||||
};
|
||||
expect(() => new ConfigurationMessage(params)).to.throw(
|
||||
'open group must be set'
|
||||
|
@ -41,6 +44,7 @@ describe('ConfigurationMessage', () => {
|
|||
activeOpenGroups: [],
|
||||
timestamp: Date.now(),
|
||||
displayName: undefined as any,
|
||||
contacts: [],
|
||||
};
|
||||
expect(() => new ConfigurationMessage(params)).to.throw(
|
||||
'displayName must be set'
|
||||
|
@ -53,6 +57,7 @@ describe('ConfigurationMessage', () => {
|
|||
activeOpenGroups: [],
|
||||
timestamp: Date.now(),
|
||||
displayName: undefined as any,
|
||||
contacts: [],
|
||||
};
|
||||
expect(() => new ConfigurationMessage(params)).to.throw(
|
||||
'displayName must be set'
|
||||
|
@ -65,6 +70,7 @@ describe('ConfigurationMessage', () => {
|
|||
activeOpenGroups: [],
|
||||
timestamp: Date.now(),
|
||||
displayName: 'displayName',
|
||||
contacts: [],
|
||||
};
|
||||
const configMessage = new ConfigurationMessage(params);
|
||||
expect(configMessage.ttl()).to.be.equal(4 * 24 * 60 * 60 * 1000);
|
||||
|
@ -175,4 +181,84 @@ describe('ConfigurationMessage', () => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ConfigurationMessageContact', () => {
|
||||
it('throws if contacts is not set', () => {
|
||||
const params = {
|
||||
activeClosedGroups: [],
|
||||
activeOpenGroups: [],
|
||||
timestamp: Date.now(),
|
||||
displayName: 'displayName',
|
||||
contacts: undefined as any,
|
||||
};
|
||||
expect(() => new ConfigurationMessage(params)).to.throw(
|
||||
'contacts must be set'
|
||||
);
|
||||
});
|
||||
it('throw if some admins are not members', () => {
|
||||
const member = TestUtils.generateFakePubKey().key;
|
||||
const admin = TestUtils.generateFakePubKey().key;
|
||||
const params = {
|
||||
publicKey: TestUtils.generateFakePubKey().key,
|
||||
name: 'groupname',
|
||||
members: [member],
|
||||
admins: [admin],
|
||||
encryptionKeyPair: TestUtils.generateFakeECKeyPair(),
|
||||
};
|
||||
|
||||
expect(() => new ConfigurationMessageClosedGroup(params)).to.throw(
|
||||
'some admins are not members'
|
||||
);
|
||||
});
|
||||
|
||||
it('throw if the contact has not a valid pubkey', () => {
|
||||
const params = {
|
||||
publicKey: '05',
|
||||
displayName: 'contactDisplayName',
|
||||
};
|
||||
|
||||
expect(() => new ConfigurationMessageContact(params)).to.throw();
|
||||
|
||||
const params2 = {
|
||||
publicKey: undefined as any,
|
||||
displayName: 'contactDisplayName',
|
||||
};
|
||||
|
||||
expect(() => new ConfigurationMessageContact(params2)).to.throw();
|
||||
});
|
||||
|
||||
it('throw if the contact has an empty disploy name', () => {
|
||||
// a display name cannot be empty. It should be undefined rather than empty
|
||||
const params2 = {
|
||||
publicKey: TestUtils.generateFakePubKey().key,
|
||||
displayName: '',
|
||||
};
|
||||
|
||||
expect(() => new ConfigurationMessageContact(params2)).to.throw();
|
||||
});
|
||||
|
||||
it('throw if the contact has a profileAvatar set but empty', () => {
|
||||
const params = {
|
||||
publicKey: TestUtils.generateFakePubKey().key,
|
||||
displayName: 'contactDisplayName',
|
||||
profilePictureURL: '',
|
||||
};
|
||||
|
||||
expect(() => new ConfigurationMessageContact(params)).to.throw(
|
||||
'profilePictureURL must either undefined or not empty'
|
||||
);
|
||||
});
|
||||
|
||||
it('throw if the contact has a profileKey set but empty', () => {
|
||||
const params = {
|
||||
publicKey: TestUtils.generateFakePubKey().key,
|
||||
displayName: 'contactDisplayName',
|
||||
profileKey: new Uint8Array(),
|
||||
};
|
||||
|
||||
expect(() => new ConfigurationMessageContact(params)).to.throw(
|
||||
'profileKey must either undefined or not empty'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -36,6 +36,7 @@ describe('ConfigurationMessage_receiving', () => {
|
|||
timestamp: Date.now(),
|
||||
identifier: 'identifier',
|
||||
displayName: 'displayName',
|
||||
contacts: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -216,6 +216,7 @@ describe('Message Utils', () => {
|
|||
activeOpenGroups: [],
|
||||
activeClosedGroups: [],
|
||||
displayName: 'displayName',
|
||||
contacts: [],
|
||||
});
|
||||
const rawMessage = await MessageUtils.toRawMessage(device, msg);
|
||||
expect(rawMessage.encryption).to.equal(EncryptionType.Fallback);
|
||||
|
|
Loading…
Reference in New Issue