Merge branch 'clearnet' into global-search-off-clearnet

pull/2130/head
warrickct 3 years ago
commit 3f4db67c1b

@ -19,6 +19,8 @@
"editMenuPaste": "Paste", "editMenuPaste": "Paste",
"editMenuPasteAndMatchStyle": "Paste and Match Style", "editMenuPasteAndMatchStyle": "Paste and Match Style",
"editMenuDelete": "Delete", "editMenuDelete": "Delete",
"editMenuDeleteContact": "Delete Contact",
"editMenuDeleteGroup": "Delete Group",
"editMenuSelectAll": "Select all", "editMenuSelectAll": "Select all",
"windowMenuClose": "Close Window", "windowMenuClose": "Close Window",
"windowMenuMinimize": "Minimize", "windowMenuMinimize": "Minimize",

@ -179,7 +179,7 @@
"chai-bytes": "^0.1.2", "chai-bytes": "^0.1.2",
"css-loader": "^3.6.0", "css-loader": "^3.6.0",
"dashdash": "1.14.1", "dashdash": "1.14.1",
"electron": "^13.1.9", "electron": "^13.6.2",
"electron-builder": "22.8.0", "electron-builder": "22.8.0",
"electron-notarize": "^0.2.0", "electron-notarize": "^0.2.0",
"eslint": "4.14.0", "eslint": "4.14.0",

@ -11,10 +11,21 @@ type Props = {
onPressEnter?: any; onPressEnter?: any;
maxLength?: number; maxLength?: number;
isGroup?: boolean; isGroup?: boolean;
dataTestId?: string;
}; };
export const SessionIdEditable = (props: Props) => { export const SessionIdEditable = (props: Props) => {
const { placeholder, onPressEnter, onChange, editable, text, value, maxLength, isGroup } = props; const {
placeholder,
onPressEnter,
onChange,
editable,
text,
value,
maxLength,
isGroup,
dataTestId,
} = props;
const inputRef = useRef(null); const inputRef = useRef(null);
useFocusMount(inputRef, editable); useFocusMount(inputRef, editable);
@ -48,6 +59,7 @@ export const SessionIdEditable = (props: Props) => {
onBlur={handleChange} onBlur={handleChange}
value={value || text} value={value || text}
maxLength={maxLength} maxLength={maxLength}
data-testid={dataTestId}
/> />
</div> </div>
); );

@ -13,8 +13,6 @@ type Props = {
isConversationListItem?: boolean; isConversationListItem?: boolean;
}; };
const UPDATE_FREQUENCY = 60 * 1000;
const TimestampContainerListItem = styled.div` const TimestampContainerListItem = styled.div`
flex-shrink: 0; flex-shrink: 0;
margin-inline-start: 6px; margin-inline-start: 6px;
@ -28,6 +26,8 @@ const TimestampContainerListItem = styled.div`
color: var(--color-text); color: var(--color-text);
`; `;
const UPDATE_FREQUENCY = 60 * 1000;
const TimestampContainerNotListItem = styled.div` const TimestampContainerNotListItem = styled.div`
font-size: 11px; font-size: 11px;
line-height: 16px; line-height: 16px;

@ -107,7 +107,7 @@ const Seed = (props: SeedProps) => {
<p className="session-modal__description">{i18n('recoveryPhraseSavePromptMain')}</p> <p className="session-modal__description">{i18n('recoveryPhraseSavePromptMain')}</p>
<SpacerXS /> <SpacerXS />
<i data-test-id="recovery-phrase-seed-modal" className="session-modal__text-highlight"> <i data-testid="recovery-phrase-seed-modal" className="session-modal__text-highlight">
{recoveryPhrase} {recoveryPhrase}
</i> </i>
</div> </div>

@ -19,7 +19,7 @@ import {
useIsPrivate, useIsPrivate,
} from '../../../hooks/useParamSelector'; } from '../../../hooks/useParamSelector';
import { MemoConversationListItemContextMenu } from '../../menu/ConversationListItemContextMenu'; import { MemoConversationListItemContextMenu } from '../../menu/ConversationListItemContextMenu';
import { HeaderItem } from './HeaderItem'; import { ConversationListItemHeaderItem } from './HeaderItem';
import { MessageItem } from './MessageItem'; import { MessageItem } from './MessageItem';
// tslint:disable-next-line: no-empty-interface // tslint:disable-next-line: no-empty-interface
@ -127,7 +127,7 @@ const ConversationListItem = (props: Props) => {
> >
<AvatarItem /> <AvatarItem />
<div className="module-conversation-list-item__content"> <div className="module-conversation-list-item__content">
<HeaderItem /> <ConversationListItemHeaderItem />
<MessageItem isMessageRequest={Boolean(isMessageRequest)} /> <MessageItem isMessageRequest={Boolean(isMessageRequest)} />
</div> </div>
</div> </div>

@ -73,7 +73,7 @@ const ListItemIcons = () => {
); );
}; };
export const HeaderItem = () => { export const ConversationListItemHeaderItem = () => {
const conversationId = useContext(ContextConversationId); const conversationId = useContext(ContextConversationId);
const convoProps = useHeaderItemProps(conversationId); const convoProps = useHeaderItemProps(conversationId);

@ -196,7 +196,9 @@ export function getDeleteContactMenuItem(
if (isPublic) { if (isPublic) {
menuItemText = window.i18n('leaveGroup'); menuItemText = window.i18n('leaveGroup');
} else { } else {
menuItemText = window.i18n('delete'); menuItemText = isGroup
? window.i18n('editMenuDeleteGroup')
: window.i18n('editMenuDeleteContact');
} }
const onClickClose = () => { const onClickClose = () => {

@ -70,7 +70,7 @@ const SignUpSessionIDShown = (props: { continueSignUp: () => void }) => {
{window.i18n('yourUniqueSessionID')} {window.i18n('yourUniqueSessionID')}
</div> </div>
</Flex> </Flex>
<SessionIdEditable editable={false} placeholder={undefined} /> <SessionIdEditable editable={false} placeholder={undefined} dataTestId="session-id-signup" />
<div className="session-description-long">{window.i18n('allUsersAreRandomly...')}</div> <div className="session-description-long">{window.i18n('allUsersAreRandomly...')}</div>
<ContinueSignUpButton continueSignUp={props.continueSignUp} /> <ContinueSignUpButton continueSignUp={props.continueSignUp} />
<TermsAndConditions /> <TermsAndConditions />

@ -362,29 +362,28 @@ export async function isMessageDuplicate({
serverTimestamp, serverTimestamp,
}: MessageId) { }: MessageId) {
const { Errors } = window.Signal.Types; const { Errors } = window.Signal.Types;
// serverId is only used for opengroupv2 // serverTimestamp is only used for opengroupv2
try { try {
let result; let result;
if (serverTimestamp) { if (serverTimestamp) {
// first try to find a duplicate with the same serverTimestamp from this sender // first try to find a duplicate with the same serverTimestamp from this sender
if (serverTimestamp) {
result = await getMessageBySenderAndServerTimestamp({ result = await getMessageBySenderAndServerTimestamp({
source, source,
serverTimestamp, serverTimestamp,
}); });
}
// if we have a result, it means a specific user sent two messages either with the same serverTimestamp. // if we have a result, it means a specific user sent two messages either with the same serverTimestamp.
// no need to do anything else, those messages must be the same // no need to do anything else, those messages must be the same
// Note: this test is not based on which conversation the user sent the message // Note: this test is not based on which conversation the user sent the message
// but we consider that a user sending two messages with the same serverTimestamp is unlikely // but we consider that a user sending two messages with the same serverTimestamp is unlikely
return Boolean(result); return Boolean(result);
} else {
result = await getMessageBySender({
source,
sourceDevice,
sentAt: timestamp,
});
} }
result = await getMessageBySender({
source,
sourceDevice,
sentAt: timestamp,
});
if (!result) { if (!result) {
return false; return false;

@ -1,48 +0,0 @@
import _ from 'lodash';
import { SignalService } from '../protobuf';
import { sha256 } from '../session/crypto';
const recentHashByConvo = new Map<string, Array<string>>();
const maxHashToKeepPerConvo = 10;
export function isDuplicateBasedOnHash(
dataMessage: SignalService.DataMessage,
conversationId: string,
sender: string
): boolean {
const toUseForHash = {
..._.omit(
SignalService.DataMessage.toObject(dataMessage),
'timestamp',
'profile',
'preview',
'profileKey'
),
conversationId,
sender,
};
if (!recentHashByConvo.has(conversationId)) {
recentHashByConvo.set(conversationId, new Array());
}
const newHash = sha256(JSON.stringify(toUseForHash));
// this can only be set based on the .set above()
let recentHashForConvo = recentHashByConvo.get(conversationId) as Array<string>;
// this hash already exists for this convo
if (recentHashForConvo.some(n => n === newHash)) {
return true;
}
// push the new hash at the end
recentHashForConvo.push(newHash);
if (recentHashForConvo.length > maxHashToKeepPerConvo) {
// slice the last maxHashToKeepPerConvo hashes
recentHashForConvo = recentHashForConvo?.slice(-maxHashToKeepPerConvo);
}
recentHashByConvo.set(conversationId, recentHashForConvo);
return false;
}
// build a hash of the data and check against recent messages

@ -26,7 +26,6 @@ import { OpenGroupRequestCommonType } from '../session/apis/open_group_api/openg
import { handleMessageJob } from './queuedJob'; import { handleMessageJob } from './queuedJob';
import { fromBase64ToArray } from '../session/utils/String'; import { fromBase64ToArray } from '../session/utils/String';
import { removeMessagePadding } from '../session/crypto/BufferPadding'; import { removeMessagePadding } from '../session/crypto/BufferPadding';
import { isDuplicateBasedOnHash } from './hashDuplicateFilter';
import { createTaskWithTimeout } from '../session/utils/TaskWithTimeout'; import { createTaskWithTimeout } from '../session/utils/TaskWithTimeout';
import { perfEnd, perfStart } from '../session/utils/Performance'; import { perfEnd, perfStart } from '../session/utils/Performance';
@ -317,7 +316,7 @@ export async function handleOpenGroupV2Message(
source: sender, source: sender,
message: dataMessage, message: dataMessage,
}; };
// WARNING this is very important that the isMessageDuplicate is made in the conversation.queueJob // WARNING this is important that the isMessageDuplicate is made in the conversation.queueJob
const isDuplicate = await isMessageDuplicate(messageCreationData); const isDuplicate = await isMessageDuplicate(messageCreationData);
if (isDuplicate) { if (isDuplicate) {
@ -325,10 +324,6 @@ export async function handleOpenGroupV2Message(
return; return;
} }
if (isDuplicateBasedOnHash(dataMessage, conversationId, sender)) {
window?.log?.info('Received duplicate message based on hash. Dropping it.');
return;
}
// this line just create an empty message with some basic stuff set. // this line just create an empty message with some basic stuff set.
// the whole decoding of data is happening in handleMessageJob() // the whole decoding of data is happening in handleMessageJob()
const msg = createMessage(messageCreationData, !isMe); const msg = createMessage(messageCreationData, !isMe);

@ -84,35 +84,6 @@ export async function getAuthToken({
return oneAtATimeGetAuth({ roomId, serverUrl }); return oneAtATimeGetAuth({ roomId, serverUrl });
} }
export type DeleteAuthTokenRequest = OpenGroupRequestCommonType & { token: string };
export const deleteAuthToken = async ({
serverUrl,
roomId,
token,
}: DeleteAuthTokenRequest): Promise<void> => {
const request: OpenGroupV2Request = {
method: 'DELETE',
room: roomId,
server: serverUrl,
isAuthRequired: true,
endpoint: 'auth_token',
forcedTokenToUse: token,
};
try {
const result = await sendApiV2Request(request);
const statusCode = parseStatusCodeFromOnionRequest(result);
if (statusCode !== 200) {
// FIXME not yet sure why this call always return 401
// window?.log?.warn(`Could not deleteAuthToken, status code: ${statusCode}`);
return;
}
return;
} catch (e) {
window?.log?.error('deleteAuthToken failed:', e);
return;
}
};
// tslint:disable: member-ordering // tslint:disable: member-ordering
export async function requestNewAuthToken({ export async function requestNewAuthToken({
serverUrl, serverUrl,

@ -14,7 +14,6 @@ import { openGroupV2GetRoomInfo } from './OpenGroupAPIV2';
import { OpenGroupServerPoller } from './OpenGroupServerPoller'; import { OpenGroupServerPoller } from './OpenGroupServerPoller';
import _ from 'lodash'; import _ from 'lodash';
import { deleteAuthToken, DeleteAuthTokenRequest } from './ApiAuth';
import autoBind from 'auto-bind'; import autoBind from 'auto-bind';
let instance: OpenGroupManagerV2 | undefined; let instance: OpenGroupManagerV2 | undefined;
@ -129,13 +128,6 @@ export class OpenGroupManagerV2 {
try { try {
const roomConvoId = getOpenGroupV2ConversationId(infos.serverUrl, infos.roomId); const roomConvoId = getOpenGroupV2ConversationId(infos.serverUrl, infos.roomId);
if (!allConvos.get(roomConvoId)) { if (!allConvos.get(roomConvoId)) {
// leave the group on the remote server
// this request doesn't throw
if (infos.token) {
await deleteAuthToken(
_.pick(infos, 'serverUrl', 'roomId', 'token') as DeleteAuthTokenRequest
);
}
// remove the roomInfos locally for this open group room // remove the roomInfos locally for this open group room
await removeV2OpenGroupRoom(roomConvoId); await removeV2OpenGroupRoom(roomConvoId);
getOpenGroupManager().removeRoomFromPolledRooms(infos); getOpenGroupManager().removeRoomFromPolledRooms(infos);

@ -12,10 +12,7 @@ import { actions as conversationActions } from '../../state/ducks/conversations'
import { getV2OpenGroupRoom, removeV2OpenGroupRoom } from '../../data/opengroups'; import { getV2OpenGroupRoom, removeV2OpenGroupRoom } from '../../data/opengroups';
import _ from 'lodash'; import _ from 'lodash';
import { getOpenGroupManager } from '../apis/open_group_api/opengroupV2/OpenGroupManagerV2'; import { getOpenGroupManager } from '../apis/open_group_api/opengroupV2/OpenGroupManagerV2';
import {
deleteAuthToken,
DeleteAuthTokenRequest,
} from '../apis/open_group_api/opengroupV2/ApiAuth';
import { deleteAllMessagesByConvoIdNoConfirmation } from '../../interactions/conversationInteractions'; import { deleteAllMessagesByConvoIdNoConfirmation } from '../../interactions/conversationInteractions';
let instance: ConversationController | null; let instance: ConversationController | null;
@ -201,12 +198,6 @@ export class ConversationController {
window?.log?.info('leaving open group v2', conversation.id); window?.log?.info('leaving open group v2', conversation.id);
const roomInfos = await getV2OpenGroupRoom(conversation.id); const roomInfos = await getV2OpenGroupRoom(conversation.id);
if (roomInfos) { if (roomInfos) {
if (roomInfos.token) {
// leave the group on the remote server
await deleteAuthToken(
_.pick(roomInfos, 'serverUrl', 'roomId', 'token') as DeleteAuthTokenRequest
);
}
getOpenGroupManager().removeRoomFromPolledRooms(roomInfos); getOpenGroupManager().removeRoomFromPolledRooms(roomInfos);
// remove the roomInfos locally for this open group room // remove the roomInfos locally for this open group room

@ -214,6 +214,7 @@ export type LocalizerKeys =
| 'groupNamePlaceholder' | 'groupNamePlaceholder'
| 'stagedPreviewThumbnail' | 'stagedPreviewThumbnail'
| 'helpUsTranslateSession' | 'helpUsTranslateSession'
| 'editMenuDeleteGroup'
| 'unreadMessages' | 'unreadMessages'
| 'documents' | 'documents'
| 'audioPermissionNeededTitle' | 'audioPermissionNeededTitle'
@ -250,6 +251,7 @@ export type LocalizerKeys =
| 'previewThumbnail' | 'previewThumbnail'
| 'photo' | 'photo'
| 'setPassword' | 'setPassword'
| 'editMenuDeleteContact'
| 'hideMenuBarTitle' | 'hideMenuBarTitle'
| 'imageCaptionIconAlt' | 'imageCaptionIconAlt'
| 'blockAll' | 'blockAll'

@ -3687,10 +3687,10 @@ electron-updater@^4.2.2:
pako "^1.0.11" pako "^1.0.11"
semver "^7.1.3" semver "^7.1.3"
electron@^13.1.9: electron@^13.6.2:
version "13.1.9" version "13.6.3"
resolved "https://registry.yarnpkg.com/electron/-/electron-13.1.9.tgz#668e2632b81e9fa21edfd32876282d3e2ff7fd76" resolved "https://registry.yarnpkg.com/electron/-/electron-13.6.3.tgz#c0217178807d3e0b2175c49dbe33ea8dac447e73"
integrity sha512-By4Zb72XNQLrPb70BXdIW3NtEHFwybP5DIQjohnCxOYONq5vojuHjNcTuWnBgMvwQ2qwykk6Tw5EwF2Pt0CWjA== integrity sha512-kevgR6/RuEhchJQbgCKhHle9HvJhi2dOJlicFZJqbbqa9BVpZARqqFDlwTSatYxmUPUJwu09FvyMwJG2DMQIng==
dependencies: dependencies:
"@electron/get" "^1.0.1" "@electron/get" "^1.0.1"
"@types/node" "^14.6.2" "@types/node" "^14.6.2"

Loading…
Cancel
Save