fix: remove all of the ConfiguratioMessage (legacy) logic
parent
0fbb0cc852
commit
c9b2d69a73
@ -1,217 +0,0 @@
|
||||
// this is not a very good name, but a configuration message is a message sent to our other devices so sync our current public and closed groups
|
||||
|
||||
import { SignalService } from '../../../../protobuf';
|
||||
import { MessageParams } from '../Message';
|
||||
import { ECKeyPair } from '../../../../receiver/keypairs';
|
||||
import { fromHexToArray } from '../../../utils/String';
|
||||
import { PubKey } from '../../../types';
|
||||
import { ContentMessage } from '..';
|
||||
|
||||
interface ConfigurationMessageParams extends MessageParams {
|
||||
activeClosedGroups: Array<ConfigurationMessageClosedGroup>;
|
||||
activeOpenGroups: Array<string>;
|
||||
displayName: string;
|
||||
profilePicture?: string;
|
||||
profileKey?: Uint8Array;
|
||||
contacts: Array<ConfigurationMessageContact>;
|
||||
}
|
||||
|
||||
export class ConfigurationMessage extends ContentMessage {
|
||||
public readonly activeClosedGroups: Array<ConfigurationMessageClosedGroup>;
|
||||
public readonly activeOpenGroups: Array<string>;
|
||||
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 });
|
||||
this.activeClosedGroups = params.activeClosedGroups;
|
||||
this.activeOpenGroups = params.activeOpenGroups;
|
||||
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');
|
||||
}
|
||||
|
||||
if (!this.activeOpenGroups) {
|
||||
throw new Error('open group must be set');
|
||||
}
|
||||
|
||||
if (!this.displayName || !this.displayName?.length) {
|
||||
throw new Error('displayName must be set');
|
||||
}
|
||||
|
||||
if (this.profilePicture && typeof this.profilePicture !== 'string') {
|
||||
throw new Error('profilePicture set but not an Uin8Array');
|
||||
}
|
||||
|
||||
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 contentProto(): SignalService.Content {
|
||||
return new SignalService.Content({
|
||||
configurationMessage: this.configurationProto(),
|
||||
});
|
||||
}
|
||||
|
||||
protected configurationProto(): SignalService.ConfigurationMessage {
|
||||
return new SignalService.ConfigurationMessage({
|
||||
closedGroups: this.mapClosedGroupsObjectToProto(this.activeClosedGroups),
|
||||
openGroups: this.activeOpenGroups,
|
||||
displayName: this.displayName,
|
||||
profilePicture: this.profilePicture,
|
||||
profileKey: this.profileKey,
|
||||
contacts: this.mapContactsObjectToProto(this.contacts),
|
||||
});
|
||||
}
|
||||
|
||||
private mapClosedGroupsObjectToProto(
|
||||
closedGroups: Array<ConfigurationMessageClosedGroup>
|
||||
): Array<SignalService.ConfigurationMessage.ClosedGroup> {
|
||||
return (closedGroups || []).map(m => m.toProto());
|
||||
}
|
||||
|
||||
private mapContactsObjectToProto(
|
||||
contacts: Array<ConfigurationMessageContact>
|
||||
): Array<SignalService.ConfigurationMessage.Contact> {
|
||||
return (contacts || []).map(m => m.toProto());
|
||||
}
|
||||
}
|
||||
|
||||
export class ConfigurationMessageContact {
|
||||
public publicKey: string;
|
||||
public displayName: string;
|
||||
public profilePictureURL?: string;
|
||||
public profileKey?: Uint8Array;
|
||||
public isApproved?: boolean;
|
||||
public isBlocked?: boolean;
|
||||
public didApproveMe?: boolean;
|
||||
|
||||
public constructor({
|
||||
publicKey,
|
||||
displayName,
|
||||
profilePictureURL,
|
||||
profileKey,
|
||||
isApproved,
|
||||
isBlocked,
|
||||
didApproveMe,
|
||||
}: {
|
||||
publicKey: string;
|
||||
displayName: string;
|
||||
profilePictureURL?: string;
|
||||
profileKey?: Uint8Array;
|
||||
isApproved?: boolean;
|
||||
isBlocked?: boolean;
|
||||
didApproveMe?: boolean;
|
||||
}) {
|
||||
this.publicKey = publicKey;
|
||||
this.displayName = displayName;
|
||||
this.profilePictureURL = profilePictureURL;
|
||||
this.profileKey = profileKey;
|
||||
this.isApproved = isApproved;
|
||||
this.isBlocked = isBlocked;
|
||||
this.didApproveMe = didApproveMe;
|
||||
|
||||
// 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,
|
||||
isApproved: this.isApproved,
|
||||
isBlocked: this.isBlocked,
|
||||
didApproveMe: this.didApproveMe,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class ConfigurationMessageClosedGroup {
|
||||
public publicKey: string;
|
||||
public name: string;
|
||||
public encryptionKeyPair: ECKeyPair;
|
||||
public members: Array<string>;
|
||||
public admins: Array<string>;
|
||||
|
||||
public constructor({
|
||||
publicKey,
|
||||
name,
|
||||
encryptionKeyPair,
|
||||
members,
|
||||
admins,
|
||||
}: {
|
||||
publicKey: string;
|
||||
name: string;
|
||||
encryptionKeyPair: ECKeyPair;
|
||||
members: Array<string>;
|
||||
admins: Array<string>;
|
||||
}) {
|
||||
this.publicKey = publicKey;
|
||||
this.name = name;
|
||||
this.encryptionKeyPair = encryptionKeyPair;
|
||||
this.members = members;
|
||||
this.admins = admins;
|
||||
|
||||
// will throw if publik key is invalid
|
||||
PubKey.cast(publicKey);
|
||||
|
||||
if (
|
||||
!encryptionKeyPair?.privateKeyData?.byteLength ||
|
||||
!encryptionKeyPair?.publicKeyData?.byteLength
|
||||
) {
|
||||
throw new Error('Encryption key pair looks invalid');
|
||||
}
|
||||
|
||||
if (!this.name?.length) {
|
||||
throw new Error('name must be set');
|
||||
}
|
||||
|
||||
if (!this.members?.length) {
|
||||
throw new Error('members must be set');
|
||||
}
|
||||
if (!this.admins?.length) {
|
||||
throw new Error('admins must be set');
|
||||
}
|
||||
|
||||
if (this.admins.some(a => !this.members.includes(a))) {
|
||||
throw new Error('some admins are not members');
|
||||
}
|
||||
}
|
||||
|
||||
public toProto(): SignalService.ConfigurationMessage.ClosedGroup {
|
||||
return new SignalService.ConfigurationMessage.ClosedGroup({
|
||||
publicKey: fromHexToArray(this.publicKey),
|
||||
name: this.name,
|
||||
encryptionKeyPair: {
|
||||
publicKey: this.encryptionKeyPair.publicKeyData,
|
||||
privateKey: this.encryptionKeyPair.privateKeyData,
|
||||
},
|
||||
members: this.members.map(fromHexToArray),
|
||||
admins: this.admins.map(fromHexToArray),
|
||||
});
|
||||
}
|
||||
}
|
@ -1,251 +0,0 @@
|
||||
import { expect } from 'chai';
|
||||
import { ECKeyPair } from '../../../../receiver/keypairs';
|
||||
import { TTL_DEFAULT } from '../../../../session/constants';
|
||||
|
||||
import {
|
||||
ConfigurationMessage,
|
||||
ConfigurationMessageClosedGroup,
|
||||
ConfigurationMessageContact,
|
||||
} from '../../../../session/messages/outgoing/controlMessage/ConfigurationMessage';
|
||||
import { TestUtils } from '../../../test-utils';
|
||||
|
||||
describe('ConfigurationMessage', () => {
|
||||
it('throw if closed group is not set', () => {
|
||||
const activeClosedGroups = null as any;
|
||||
const params = {
|
||||
activeClosedGroups,
|
||||
activeOpenGroups: [],
|
||||
timestamp: Date.now(),
|
||||
displayName: 'displayName',
|
||||
contacts: [],
|
||||
};
|
||||
expect(() => new ConfigurationMessage(params)).to.throw('closed group must be set');
|
||||
});
|
||||
|
||||
it('throw if open group is not set', () => {
|
||||
const activeOpenGroups = null as any;
|
||||
const params = {
|
||||
activeClosedGroups: [],
|
||||
activeOpenGroups,
|
||||
timestamp: Date.now(),
|
||||
displayName: 'displayName',
|
||||
contacts: [],
|
||||
};
|
||||
expect(() => new ConfigurationMessage(params)).to.throw('open group must be set');
|
||||
});
|
||||
|
||||
it('throw if display name is not set', () => {
|
||||
const params = {
|
||||
activeClosedGroups: [],
|
||||
activeOpenGroups: [],
|
||||
timestamp: Date.now(),
|
||||
displayName: undefined as any,
|
||||
contacts: [],
|
||||
};
|
||||
expect(() => new ConfigurationMessage(params)).to.throw('displayName must be set');
|
||||
});
|
||||
|
||||
it('throw if display name is set but empty', () => {
|
||||
const params = {
|
||||
activeClosedGroups: [],
|
||||
activeOpenGroups: [],
|
||||
timestamp: Date.now(),
|
||||
displayName: undefined as any,
|
||||
contacts: [],
|
||||
};
|
||||
expect(() => new ConfigurationMessage(params)).to.throw('displayName must be set');
|
||||
});
|
||||
|
||||
it('ttl is 4 days', () => {
|
||||
const params = {
|
||||
activeClosedGroups: [],
|
||||
activeOpenGroups: [],
|
||||
timestamp: Date.now(),
|
||||
displayName: 'displayName',
|
||||
contacts: [],
|
||||
};
|
||||
const configMessage = new ConfigurationMessage(params);
|
||||
expect(configMessage.ttl()).to.be.equal(TTL_DEFAULT.TTL_MAX);
|
||||
});
|
||||
|
||||
describe('ConfigurationMessageClosedGroup', () => {
|
||||
it('throw if closed group has no encryptionkeypair', () => {
|
||||
const member = TestUtils.generateFakePubKey().key;
|
||||
const params = {
|
||||
publicKey: TestUtils.generateFakePubKey().key,
|
||||
name: 'groupname',
|
||||
members: [member],
|
||||
admins: [member],
|
||||
encryptionKeyPair: undefined as any,
|
||||
};
|
||||
|
||||
expect(() => new ConfigurationMessageClosedGroup(params)).to.throw(
|
||||
'Encryption key pair looks invalid'
|
||||
);
|
||||
});
|
||||
|
||||
it('throw if closed group has invalid encryptionkeypair', () => {
|
||||
const member = TestUtils.generateFakePubKey().key;
|
||||
const params = {
|
||||
publicKey: TestUtils.generateFakePubKey().key,
|
||||
name: 'groupname',
|
||||
members: [member],
|
||||
admins: [member],
|
||||
encryptionKeyPair: new ECKeyPair(new Uint8Array(), new Uint8Array()),
|
||||
};
|
||||
|
||||
expect(() => new ConfigurationMessageClosedGroup(params)).to.throw(
|
||||
'Encryption key pair looks invalid'
|
||||
);
|
||||
});
|
||||
|
||||
it('throw if closed group has invalid pubkey', () => {
|
||||
const member = TestUtils.generateFakePubKey().key;
|
||||
const params = {
|
||||
publicKey: 'invalidpubkey',
|
||||
name: 'groupname',
|
||||
members: [member],
|
||||
admins: [member],
|
||||
encryptionKeyPair: TestUtils.generateFakeECKeyPair(),
|
||||
};
|
||||
|
||||
expect(() => new ConfigurationMessageClosedGroup(params)).to.throw();
|
||||
});
|
||||
|
||||
it('throw if closed group has invalid name', () => {
|
||||
const member = TestUtils.generateFakePubKey().key;
|
||||
const params = {
|
||||
publicKey: TestUtils.generateFakePubKey().key,
|
||||
name: '',
|
||||
members: [member],
|
||||
admins: [member],
|
||||
encryptionKeyPair: TestUtils.generateFakeECKeyPair(),
|
||||
};
|
||||
|
||||
expect(() => new ConfigurationMessageClosedGroup(params)).to.throw('name must be set');
|
||||
});
|
||||
|
||||
it('throw if members is empty', () => {
|
||||
const member = TestUtils.generateFakePubKey().key;
|
||||
const params = {
|
||||
publicKey: TestUtils.generateFakePubKey().key,
|
||||
name: 'groupname',
|
||||
members: [],
|
||||
admins: [member],
|
||||
encryptionKeyPair: TestUtils.generateFakeECKeyPair(),
|
||||
};
|
||||
|
||||
expect(() => new ConfigurationMessageClosedGroup(params)).to.throw('members must be set');
|
||||
});
|
||||
|
||||
it('throw if admins is empty', () => {
|
||||
const member = TestUtils.generateFakePubKey().key;
|
||||
const params = {
|
||||
publicKey: TestUtils.generateFakePubKey().key,
|
||||
name: 'groupname',
|
||||
members: [member],
|
||||
admins: [],
|
||||
encryptionKeyPair: TestUtils.generateFakeECKeyPair(),
|
||||
};
|
||||
|
||||
expect(() => new ConfigurationMessageClosedGroup(params)).to.throw('admins 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'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
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 display name', () => {
|
||||
// a display name cannot be empty nor undefined
|
||||
|
||||
expect(() => new ConfigurationMessageContact(params2)).to.throw();
|
||||
|
||||
const params2 = {
|
||||
publicKey: TestUtils.generateFakePubKey().key,
|
||||
displayName: '',
|
||||
};
|
||||
|
||||
expect(() => new ConfigurationMessageContact(params2)).to.throw();
|
||||
});
|
||||
|
||||
it('throw if the contact has a profilePictureURL 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'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,20 +1,5 @@
|
||||
// `missingCaseError` is useful for compile-time checking that all `case`s in
|
||||
// a `switch` statement have been handled, e.g.
|
||||
//
|
||||
// type AttachmentType = 'media' | 'documents';
|
||||
//
|
||||
// const type: AttachmentType = selectedTab;
|
||||
// switch (type) {
|
||||
// case 'media':
|
||||
// return <MediaGridItem/>;
|
||||
// case 'documents':
|
||||
// return <DocumentListItem/>;
|
||||
// default:
|
||||
// return missingCaseError(type);
|
||||
// }
|
||||
//
|
||||
// If we extended `AttachmentType` to `'media' | 'documents' | 'links'` the code
|
||||
// above would trigger a compiler error stating that `'links'` has not been
|
||||
// handled by our `switch` / `case` statement which is useful for code
|
||||
// maintenance and system evolution.
|
||||
|
||||
export const missingCaseError = (x: never): TypeError => new TypeError(`Unhandled case: ${x}`);
|
||||
|
Loading…
Reference in New Issue