Support for blocking groups on mobile, via group/blocked syncs

pull/27/head^2
Scott Nonnenberg 7 years ago
parent cfe561b3eb
commit 9c399624cc

@ -1222,6 +1222,10 @@
"message": "Unblock this contact to send a message.", "message": "Unblock this contact to send a message.",
"description": "Brief message shown when trying to message a blocked number" "description": "Brief message shown when trying to message a blocked number"
}, },
"unblockGroupToSend": {
"message": "Unblock this group to send a message.",
"description": "Brief message shown when trying to message a blocked group"
},
"youChangedTheTimer": { "youChangedTheTimer": {
"message": "You set the disappearing message timer to $time$", "message": "You set the disappearing message timer to $time$",
"description": "description":

@ -802,6 +802,7 @@
} }
function onConfiguration(ev) { function onConfiguration(ev) {
storage.put('read-receipt-setting', ev.configuration.readReceipts); storage.put('read-receipt-setting', ev.configuration.readReceipts);
ev.confirm();
} }
async function onContactReceived(ev) { async function onContactReceived(ev) {
@ -919,6 +920,12 @@
updates.left = true; updates.left = true;
} }
if (details.blocked === true) {
storage.addBlockedGroup(id);
} else if (details.blocked === false) {
storage.removeBlockedGroup(id);
}
await wrapDeferred(conversation.save(updates)); await wrapDeferred(conversation.save(updates));
const { expireTimer } = details; const { expireTimer } = details;
const isValidExpireTimer = typeof expireTimer === 'number'; const isValidExpireTimer = typeof expireTimer === 'number';

@ -4,27 +4,54 @@
(function() { (function() {
'use strict'; 'use strict';
const BLOCKED_NUMBERS_ID = 'blocked';
const BLOCKED_GROUPS_ID = 'blocked-groups';
storage.isBlocked = number => { storage.isBlocked = number => {
const numbers = storage.get('blocked', []); const numbers = storage.get(BLOCKED_NUMBERS_ID, []);
return _.include(numbers, number); return _.include(numbers, number);
}; };
storage.addBlockedNumber = number => { storage.addBlockedNumber = number => {
const numbers = storage.get('blocked', []); const numbers = storage.get(BLOCKED_NUMBERS_ID, []);
if (_.include(numbers, number)) { if (_.include(numbers, number)) {
return; return;
} }
window.log.info('adding', number, 'to blocked list'); window.log.info('adding', number, 'to blocked list');
storage.put('blocked', numbers.concat(number)); storage.put(BLOCKED_NUMBERS_ID, numbers.concat(number));
}; };
storage.removeBlockedNumber = number => { storage.removeBlockedNumber = number => {
const numbers = storage.get('blocked', []); const numbers = storage.get(BLOCKED_NUMBERS_ID, []);
if (!_.include(numbers, number)) { if (!_.include(numbers, number)) {
return; return;
} }
window.log.info('removing', number, 'from blocked list'); window.log.info('removing', number, 'from blocked list');
storage.put('blocked', _.without(numbers, number)); storage.put(BLOCKED_NUMBERS_ID, _.without(numbers, number));
};
storage.isGroupBlocked = groupId => {
const groupIds = storage.get(BLOCKED_GROUPS_ID, []);
return _.include(groupIds, groupId);
};
storage.addBlockedGroup = groupId => {
const groupIds = storage.get(BLOCKED_GROUPS_ID, []);
if (_.include(groupIds, groupId)) {
return;
}
window.log.info(`adding groupId(${groupId}) to blocked list`);
storage.put(BLOCKED_GROUPS_ID, groupIds.concat(groupId));
};
storage.removeBlockedGroup = groupId => {
const groupIds = storage.get(BLOCKED_GROUPS_ID, []);
if (!_.include(groupIds, groupId)) {
return;
}
window.log.info(`removing group(${groupId} from blocked list`);
storage.put(BLOCKED_GROUPS_ID, _.without(groupIds, groupId));
}; };
})(); })();

@ -29,6 +29,11 @@
return { toastMessage: i18n('unblockToSend') }; return { toastMessage: i18n('unblockToSend') };
}, },
}); });
Whisper.BlockedGroupToast = Whisper.ToastView.extend({
render_attributes() {
return { toastMessage: i18n('unblockGroupToSend') };
},
});
Whisper.LeftGroupToast = Whisper.ToastView.extend({ Whisper.LeftGroupToast = Whisper.ToastView.extend({
render_attributes() { render_attributes() {
return { toastMessage: i18n('youLeftTheGroup') }; return { toastMessage: i18n('youLeftTheGroup') };
@ -1436,6 +1441,9 @@
if (this.model.isPrivate() && storage.isBlocked(this.model.id)) { if (this.model.isPrivate() && storage.isBlocked(this.model.id)) {
toast = new Whisper.BlockedToast(); toast = new Whisper.BlockedToast();
} }
if (!this.model.isPrivate() && storage.isGroupBlocked(this.model.id)) {
toast = new Whisper.BlockedGroupToast();
}
if (!this.model.isPrivate() && this.model.get('left')) { if (!this.model.isPrivate() && this.model.get('left')) {
toast = new Whisper.LeftGroupToast(); toast = new Whisper.LeftGroupToast();
} }

@ -727,6 +727,16 @@ MessageReceiver.prototype.extend({
} }
return p.then(() => return p.then(() =>
this.processDecrypted(envelope, msg, this.number).then(message => { this.processDecrypted(envelope, msg, this.number).then(message => {
const groupId = message.group && message.group.id;
if (groupId && this.isGroupBlocked(groupId)) {
window.log.warn(
`Message ${this.getEnvelopeId(
envelope
)} ignored; destined for blocked group`
);
return this.removeFromCache(envelope);
}
const ev = new Event('sent'); const ev = new Event('sent');
ev.confirm = this.removeFromCache.bind(this, envelope); ev.confirm = this.removeFromCache.bind(this, envelope);
ev.data = { ev.data = {
@ -751,6 +761,16 @@ MessageReceiver.prototype.extend({
} }
return p.then(() => return p.then(() =>
this.processDecrypted(envelope, msg, envelope.source).then(message => { this.processDecrypted(envelope, msg, envelope.source).then(message => {
const groupId = message.group && message.group.id;
if (groupId && this.isGroupBlocked(groupId)) {
window.log.warn(
`Message ${this.getEnvelopeId(
envelope
)} ignored; destined for blocked group`
);
return this.removeFromCache(envelope);
}
const ev = new Event('message'); const ev = new Event('message');
ev.confirm = this.removeFromCache.bind(this, envelope); ev.confirm = this.removeFromCache.bind(this, envelope);
ev.data = { ev.data = {
@ -991,10 +1011,22 @@ MessageReceiver.prototype.extend({
handleBlocked(envelope, blocked) { handleBlocked(envelope, blocked) {
window.log.info('Setting these numbers as blocked:', blocked.numbers); window.log.info('Setting these numbers as blocked:', blocked.numbers);
textsecure.storage.put('blocked', blocked.numbers); textsecure.storage.put('blocked', blocked.numbers);
const groupIds = _.map(blocked.groupIds, groupId => groupId.toBinary());
window.log.info(
'Setting these groups as blocked:',
groupIds.map(groupId => `group(${groupId})`)
);
textsecure.storage.put('blocked-groups', groupIds);
return this.removeFromCache(envelope);
}, },
isBlocked(number) { isBlocked(number) {
return textsecure.storage.get('blocked', []).indexOf(number) >= 0; return textsecure.storage.get('blocked', []).indexOf(number) >= 0;
}, },
isGroupBlocked(groupId) {
return textsecure.storage.get('blocked-groups', []).indexOf(groupId) >= 0;
},
handleAttachment(attachment) { handleAttachment(attachment) {
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
attachment.id = attachment.id.toString(); attachment.id = attachment.id.toString();

@ -208,6 +208,7 @@ message SyncMessage {
message Blocked { message Blocked {
repeated string numbers = 1; repeated string numbers = 1;
repeated bytes groupIds = 2;
} }
message Request { message Request {
@ -303,4 +304,5 @@ message GroupDetails {
optional bool active = 5 [default = true]; optional bool active = 5 [default = true];
optional uint32 expireTimer = 6; optional uint32 expireTimer = 6;
optional string color = 7; optional string color = 7;
optional bool blocked = 8;
} }

@ -126,12 +126,6 @@
{ {
type: 'remove', type: 'remove',
isMe: true, isMe: true,
contacts: [
{
phoneNumber: '(202) 555-1000',
profileName: 'Mr. Fire',
},
],
}, },
]} ]}
i18n={util.i18n} i18n={util.i18n}

@ -71,14 +71,14 @@ export class GroupNotification extends React.Component<Props> {
/> />
); );
case 'remove': case 'remove':
if (!contacts || !contacts.length) {
throw new Error('Group update is missing contacts');
}
if (isMe) { if (isMe) {
return i18n('youLeftTheGroup'); return i18n('youLeftTheGroup');
} }
if (!contacts || !contacts.length) {
throw new Error('Group update is missing contacts');
}
return ( return (
<Intl <Intl
i18n={i18n} i18n={i18n}

Loading…
Cancel
Save