encrypted pictures for public chats

pull/661/head
sachaaaaa 5 years ago
parent 0122fb8603
commit a29f0a4120

@ -985,6 +985,12 @@
// so we could disable this here
// or least it enable for the quickest response
window.lokiPublicChatAPI.setProfileName(newName);
window
.getConversations()
.filter(convo => convo.isPublic() && !convo.isRss())
.forEach(convo =>
convo.trigger('ourAvatarChanged', { url, profileKey })
);
},
});
}

@ -157,6 +157,15 @@
this.on('expiration-change', this.updateAndMerge);
this.on('expired', this.onExpired);
this.on('ourAvatarChanged', avatar =>
this.updateAvatarOnPublicChat(avatar)
);
// Always share profile pics with public chats
if (this.isPublic) {
this.set('profileSharing', true);
}
const sealedSender = this.get('sealedSender');
if (sealedSender === undefined) {
this.set({ sealedSender: SEALED_SENDER.UNKNOWN });
@ -1677,6 +1686,27 @@
);
},
async updateAvatarOnPublicChat({ url, profileKey }) {
if (!this.isPublic()) {
return;
}
if (this.isRss()) {
return;
}
if (!this.get('profileSharing')) {
return;
}
if (profileKey && typeof profileKey !== 'string') {
// eslint-disable-next-line no-param-reassign
profileKey = window.Signal.Crypto.arrayBufferToBase64(profileKey);
}
const serverAPI = await lokiPublicChatAPI.findOrCreateServer(
this.get('server')
);
await serverAPI.setAvatar(url, profileKey);
},
async handleMessageSendResult({
failoverNumbers,
unidentifiedDeliveries,

@ -14,6 +14,7 @@ const PUBLICCHAT_MOD_POLL_EVERY = 30 * 1000; // 30s
const PUBLICCHAT_MIN_TIME_BETWEEN_DUPLICATE_MESSAGES = 10 * 1000; // 10s
const HOMESERVER_USER_ANNOTATION_TYPE = 'network.loki.messenger.homeserver';
const AVATAR_USER_ANNOTATION_TYPE = 'network.loki.messenger.avatar';
const MESSAGE_ATTACHMENT_TYPE = 'net.app.core.oembed';
const LOKI_ATTACHMENT_TYPE = 'attachment';
const LOKI_PREVIEW_TYPE = 'preview';
@ -133,6 +134,17 @@ class LokiAppDotNetAPI extends EventEmitter {
})
);
}
async setAvatar(url, profileKey) {
await Promise.all(
this.servers.map(async server => {
// this may fail
// but we can't create a sql table to remember to retry forever
// I think we just silently fail for now
await server.setAvatar(url, profileKey);
})
);
}
}
class LokiAppDotNetServerAPI {
@ -254,6 +266,14 @@ class LokiAppDotNetServerAPI {
return res.response.data.annotations || [];
}
async setAvatar(url, profileKey) {
let value = null;
if (url && profileKey) {
value = { url, profileKey };
}
return this.setSelfAnnotation(AVATAR_USER_ANNOTATION_TYPE, value);
}
// get active token for this server
async getOrRefreshServerToken(forceRefresh = false) {
let token;
@ -938,7 +958,16 @@ class LokiPublicChannelAPI {
}
// timestamp is the only required field we've had since the first deployed version
const { timestamp, quote, avatar } = noteValue;
const { timestamp, quote } = noteValue;
let profileKey = null;
let avatar = null;
const avatarNote = adnMessage.user.annotations.find(
note => note.type === AVATAR_USER_ANNOTATION_TYPE
);
if (avatarNote) {
({ profileKey, url: avatar } = avatarNote.value);
}
if (quote) {
// TODO: Enable quote attachments again using proper ADN style
@ -1002,6 +1031,7 @@ class LokiPublicChannelAPI {
preview,
quote,
avatar,
profileKey,
};
}
@ -1070,12 +1100,21 @@ class LokiPublicChannelAPI {
return false; // Invalid or delete message
}
const pubKey = adnMessage.user.username;
const messengerData = await this.getMessengerData(adnMessage);
if (messengerData === false) {
return false;
}
const { timestamp, quote, attachments, preview } = messengerData;
const {
timestamp,
quote,
attachments,
preview,
avatar,
profileKey,
} = messengerData;
if (!timestamp) {
return false; // Invalid message
}
@ -1083,7 +1122,7 @@ class LokiPublicChannelAPI {
// Duplicate check
const isDuplicate = message => {
// The username in this case is the users pubKey
const sameUsername = message.username === adnMessage.user.username;
const sameUsername = message.username === pubKey;
const sameText = message.text === adnMessage.text;
// Don't filter out messages that are too far apart from each other
const timestampsSimilar =
@ -1103,7 +1142,7 @@ class LokiPublicChannelAPI {
this.lastMessagesCache = [
...this.lastMessagesCache,
{
username: adnMessage.user.username,
username: pubKey,
text: adnMessage.text,
timestamp,
},
@ -1112,7 +1151,7 @@ class LokiPublicChannelAPI {
const from = adnMessage.user.name || 'Anonymous'; // profileName
// if us
if (adnMessage.user.username === ourNumber) {
if (pubKey === ourNumber) {
// update the last name we saw from ourself
lastProfileName = from;
}
@ -1133,12 +1172,8 @@ class LokiPublicChannelAPI {
if (homeServerPubKeys[homeServer] === undefined) {
homeServerPubKeys[homeServer] = [];
}
if (
homeServerPubKeys[homeServer].indexOf(
`@${adnMessage.user.username}`
) === -1
) {
homeServerPubKeys[homeServer].push(`@${adnMessage.user.username}`);
if (homeServerPubKeys[homeServer].indexOf(`@${pubKey}`) === -1) {
homeServerPubKeys[homeServer].push(`@${pubKey}`);
}
// generate signal message object
@ -1146,7 +1181,7 @@ class LokiPublicChannelAPI {
serverId: adnMessage.id,
clientVerified: true,
friendRequest: false,
source: adnMessage.user.username,
source: pubKey,
sourceDevice: 1,
timestamp,
@ -1163,7 +1198,7 @@ class LokiPublicChannelAPI {
},
flags: 0,
expireTimer: 0,
profileKey: null,
profileKey,
timestamp,
received_at: receivedAt,
sent_at: timestamp,
@ -1172,6 +1207,7 @@ class LokiPublicChannelAPI {
preview,
profile: {
displayName: from,
avatar,
},
},
};
@ -1191,8 +1227,6 @@ class LokiPublicChannelAPI {
// slave to primary map for this group of messages
let slavePrimaryMap = {};
// pubKey to avatar
let avatarMap = {};
// reduce list of servers into verified maps and keys
const verifiedPrimaryPKs = await Object.keys(homeServerPubKeys).reduce(
@ -1211,10 +1245,6 @@ class LokiPublicChannelAPI {
// should not be any collisions, since each pubKey can only have one home server
slavePrimaryMap = { ...slavePrimaryMap, ...result.slaveMap };
// merge this servers avatarMap into our map
// again shouldn't be any collisions
avatarMap = { ...avatarMap, ...serverAPI.avatarMap };
// copy verified pub keys into result
return curVal.concat(result.verifiedPrimaryPKs);
},
@ -1228,13 +1258,6 @@ class LokiPublicChannelAPI {
.reduce((retval, messageData) => {
// if a known slave
if (slavePrimaryMap[messageData.source]) {
// pop primary device avatars in
if (avatarMap[slavePrimaryMap[messageData.source]]) {
// modify messageData for user's avatar
messageData.message.profile.avatar =
avatarMap[slavePrimaryMap[messageData.source]];
}
// delay sending the message
if (retval[messageData.source] === undefined) {
retval[messageData.source] = [messageData];
@ -1243,13 +1266,6 @@ class LokiPublicChannelAPI {
}
} else {
// not from a paired/slave/unregistered device
// pop current device avatars in
if (avatarMap[messageData.source]) {
// modify messageData for user's avatar
messageData.message.profile.avatar = avatarMap[messageData.source];
}
// send event now
this.serverAPI.chatAPI.emit('publicMessage', {
message: messageData,
@ -1270,7 +1286,19 @@ class LokiPublicChannelAPI {
/* eslint-disable no-param-reassign */
this.primaryUserProfileName = verifiedDeviceResults.reduce(
(mapOut, user) => {
mapOut[user.username] = user.name;
let avatar = null;
let profileKey = null;
const avatarNote = user.annotations.find(
note => note.type === AVATAR_USER_ANNOTATION_TYPE
);
if (avatarNote) {
({ profileKey, url: avatar } = avatarNote.value);
}
mapOut[user.username] = {
name: user.name,
avatar,
profileKey,
};
return mapOut;
},
{}
@ -1294,9 +1322,12 @@ class LokiPublicChannelAPI {
if (slavePrimaryMap[messageData.source]) {
// rewrite source, profile
messageData.source = primaryPubKey;
messageData.message.profile.displayName = this.primaryUserProfileName[
const { name, avatar, profileKey } = this.primaryUserProfileName[
primaryPubKey
];
messageData.message.profile.displayName = name;
messageData.message.profile.avatar = avatar;
messageData.message.profileKey = profileKey;
}
this.serverAPI.chatAPI.emit('publicMessage', {
message: messageData,
@ -1408,8 +1439,6 @@ class LokiPublicChannelAPI {
LokiPublicChannelAPI.getAnnotationFromPreview
);
const avatarAnnotation = data.profile.avatar || null;
const payload = {
text,
annotations: [
@ -1417,8 +1446,6 @@ class LokiPublicChannelAPI {
type: 'network.loki.messenger.publicChat',
value: {
timestamp: messageTimeStamp,
// can remove after this release
avatar: avatarAnnotation,
},
},
...attachmentAnnotations,

@ -17,6 +17,10 @@ class LokiFileServerInstance {
this._adnApi = new LokiAppDotNetAPI(ourKey);
this.avatarMap = {};
}
// FIXME: this is not file-server specific
// and is currently called by LokiAppDotNetAPI.
// LokiAppDotNetAPI (base) should not know about LokiFileServer.
async establishConnection(serverUrl) {
// FIXME: we don't always need a token...
this._server = await this._adnApi.findOrCreateServer(serverUrl);

@ -172,7 +172,11 @@ MessageReceiver.prototype.extend({
message.source,
'private'
);
await this.updateProfile(conversation, message.message.profile);
await this.updateProfile(
conversation,
message.message.profile,
message.message.profileKey
);
}
const ev = new Event('message');
@ -1295,7 +1299,7 @@ MessageReceiver.prototype.extend({
} catch (e) {
window.log.error(`Could not decrypt profile image: ${e}`);
}
}
}
newProfile.avatar = path;
}
} else {

Loading…
Cancel
Save