Add timestamp utilities with helpful names
This commit is contained in:
parent
9fa3359477
commit
a75402d290
8 changed files with 71 additions and 17 deletions
|
@ -5,6 +5,7 @@
|
|||
|
||||
import { fromEncodedBinaryToArrayBuffer, constantTimeEqual } from './Crypto';
|
||||
import { isNotNil } from './util/isNotNil';
|
||||
import { isMoreRecentThan } from './util/timestamp';
|
||||
|
||||
const TIMESTAMP_THRESHOLD = 5 * 1000; // 5 seconds
|
||||
const Direction = {
|
||||
|
@ -839,7 +840,7 @@ export class SignalProtocolStore extends EventsMixin {
|
|||
isNonBlockingApprovalRequired(identityRecord: IdentityKeyType): boolean {
|
||||
return (
|
||||
!identityRecord.firstUse &&
|
||||
Date.now() - identityRecord.timestamp < TIMESTAMP_THRESHOLD &&
|
||||
isMoreRecentThan(identityRecord.timestamp, TIMESTAMP_THRESHOLD) &&
|
||||
!identityRecord.nonblockingApproval
|
||||
);
|
||||
}
|
||||
|
@ -1138,7 +1139,7 @@ export class SignalProtocolStore extends EventsMixin {
|
|||
}
|
||||
|
||||
if (
|
||||
Date.now() - identityRecord.timestamp < TIMESTAMP_THRESHOLD &&
|
||||
isMoreRecentThan(identityRecord.timestamp, TIMESTAMP_THRESHOLD) &&
|
||||
!identityRecord.nonblockingApproval &&
|
||||
!identityRecord.firstUse
|
||||
) {
|
||||
|
|
|
@ -8,6 +8,9 @@ import { getTitleBarVisibility, TitleBarVisibility } from './types/Settings';
|
|||
import { isWindowDragElement } from './util/isWindowDragElement';
|
||||
import { assert } from './util/assert';
|
||||
import { routineProfileRefresh } from './routineProfileRefresh';
|
||||
import { isMoreRecentThan, isOlderThan } from './util/timestamp';
|
||||
|
||||
const MAX_ATTACHMENT_DOWNLOAD_AGE = 3600 * 72 * 1000;
|
||||
|
||||
export async function startApp(): Promise<void> {
|
||||
window.startupProcessingQueue = new window.Signal.Util.StartupQueue();
|
||||
|
@ -555,12 +558,11 @@ export async function startApp(): Promise<void> {
|
|||
};
|
||||
|
||||
// How long since we were last running?
|
||||
const now = Date.now();
|
||||
const lastHeartbeat = window.storage.get('lastHeartbeat');
|
||||
await window.storage.put('lastStartup', Date.now());
|
||||
|
||||
const THIRTY_DAYS = 30 * 24 * 60 * 60 * 1000;
|
||||
if (lastHeartbeat > 0 && now - lastHeartbeat > THIRTY_DAYS) {
|
||||
if (lastHeartbeat > 0 && isOlderThan(lastHeartbeat, THIRTY_DAYS)) {
|
||||
await unlinkAndDisconnect();
|
||||
}
|
||||
|
||||
|
@ -2097,12 +2099,14 @@ export async function startApp(): Promise<void> {
|
|||
// once we stop processing the queue.
|
||||
window.attachmentDownloadQueue = undefined;
|
||||
|
||||
const THREE_DAYS_AGO = Date.now() - 3600 * 72 * 1000;
|
||||
const MAX_ATTACHMENT_MSGS_TO_DOWNLOAD = 250;
|
||||
const attachmentsToDownload = attachmentDownloadQueue.filter(
|
||||
(message, index) =>
|
||||
index <= MAX_ATTACHMENT_MSGS_TO_DOWNLOAD ||
|
||||
message.getReceivedAt() > THREE_DAYS_AGO ||
|
||||
isMoreRecentThan(
|
||||
message.getReceivedAt(),
|
||||
MAX_ATTACHMENT_DOWNLOAD_AGE
|
||||
) ||
|
||||
// Stickers and long text attachments has to be downloaded for UI
|
||||
// to display the message properly.
|
||||
message.hasRequiredAttachmentDownloads()
|
||||
|
|
|
@ -8,12 +8,14 @@ import { assert } from './util/assert';
|
|||
import { missingCaseError } from './util/missingCaseError';
|
||||
import { isNormalNumber } from './util/isNormalNumber';
|
||||
import { map, take } from './util/iterables';
|
||||
import { isOlderThan } from './util/timestamp';
|
||||
import { ConversationModel } from './models/conversations';
|
||||
|
||||
const STORAGE_KEY = 'lastAttemptedToRefreshProfilesAt';
|
||||
const MAX_AGE_TO_BE_CONSIDERED_ACTIVE = 30 * 24 * 60 * 60 * 1000;
|
||||
const MAX_AGE_TO_BE_CONSIDERED_RECENTLY_REFRESHED = 1 * 24 * 60 * 60 * 1000;
|
||||
const MAX_CONVERSATIONS_TO_REFRESH = 50;
|
||||
const MIN_ELAPSED_DURATION_TO_REFRESH_AGAIN = 12 * 3600 * 1000;
|
||||
|
||||
// This type is a little stricter than what's on `window.storage`, and only requires what
|
||||
// we need for easier testing.
|
||||
|
@ -81,8 +83,7 @@ function hasEnoughTimeElapsedSinceLastRefresh(storage: StorageType): boolean {
|
|||
}
|
||||
|
||||
if (isNormalNumber(storedValue)) {
|
||||
const twelveHoursAgo = Date.now() - 43200000;
|
||||
return storedValue < twelveHoursAgo;
|
||||
return isOlderThan(storedValue, MIN_ELAPSED_DURATION_TO_REFRESH_AGAIN);
|
||||
}
|
||||
|
||||
assert(
|
||||
|
|
37
ts/test-both/util/timestamp_test.ts
Normal file
37
ts/test-both/util/timestamp_test.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
|
||||
import { isOlderThan, isMoreRecentThan } from '../../util/timestamp';
|
||||
|
||||
const ONE_HOUR = 3600 * 1000;
|
||||
const ONE_DAY = 24 * ONE_HOUR;
|
||||
|
||||
describe('timestamp', () => {
|
||||
describe('isOlderThan', () => {
|
||||
it('returns false on recent and future timestamps', () => {
|
||||
assert.isFalse(isOlderThan(Date.now(), ONE_DAY));
|
||||
assert.isFalse(isOlderThan(Date.now() + ONE_DAY, ONE_DAY));
|
||||
});
|
||||
|
||||
it('returns true on old enough timestamps', () => {
|
||||
assert.isFalse(isOlderThan(Date.now() - ONE_DAY + ONE_HOUR, ONE_DAY));
|
||||
assert.isTrue(isOlderThan(Date.now() - ONE_DAY - ONE_HOUR, ONE_DAY));
|
||||
});
|
||||
});
|
||||
|
||||
describe('isMoreRecentThan', () => {
|
||||
it('returns true on recent and future timestamps', () => {
|
||||
assert.isTrue(isMoreRecentThan(Date.now(), ONE_DAY));
|
||||
assert.isTrue(isMoreRecentThan(Date.now() + ONE_DAY, ONE_DAY));
|
||||
});
|
||||
|
||||
it('returns false on old enough timestamps', () => {
|
||||
assert.isTrue(isMoreRecentThan(Date.now() - ONE_DAY + ONE_HOUR, ONE_DAY));
|
||||
assert.isFalse(
|
||||
isMoreRecentThan(Date.now() - ONE_DAY - ONE_HOUR, ONE_DAY)
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -17,8 +17,10 @@ import ProvisioningCipher from './ProvisioningCipher';
|
|||
import WebSocketResource, {
|
||||
IncomingWebSocketRequest,
|
||||
} from './WebsocketResources';
|
||||
import { isMoreRecentThan, isOlderThan } from '../util/timestamp';
|
||||
|
||||
const ARCHIVE_AGE = 30 * 24 * 60 * 60 * 1000;
|
||||
const PREKEY_ROTATION_AGE = 24 * 60 * 60 * 1000;
|
||||
|
||||
function getIdentifier(id: string) {
|
||||
if (!id || !id.length) {
|
||||
|
@ -321,10 +323,9 @@ export default class AccountManager extends EventTarget {
|
|||
existingKeys.sort((a, b) => (b.created_at || 0) - (a.created_at || 0));
|
||||
const confirmedKeys = existingKeys.filter(key => key.confirmed);
|
||||
|
||||
const ONE_DAY_AGO = Date.now() - 24 * 60 * 60 * 1000;
|
||||
if (
|
||||
confirmedKeys.length >= 3 &&
|
||||
confirmedKeys[0].created_at > ONE_DAY_AGO
|
||||
isMoreRecentThan(confirmedKeys[0].created_at, PREKEY_ROTATION_AGE)
|
||||
) {
|
||||
window.log.warn(
|
||||
'rotateSignedPreKey: 3+ confirmed keys, most recent is less than a day old. Cancelling rotation.'
|
||||
|
@ -437,9 +438,8 @@ export default class AccountManager extends EventTarget {
|
|||
return;
|
||||
}
|
||||
const createdAt = key.created_at || 0;
|
||||
const age = Date.now() - createdAt;
|
||||
|
||||
if (age > ARCHIVE_AGE) {
|
||||
if (isOlderThan(createdAt, ARCHIVE_AGE)) {
|
||||
window.log.info(
|
||||
'Removing confirmed signed prekey:',
|
||||
key.keyId,
|
||||
|
@ -463,8 +463,7 @@ export default class AccountManager extends EventTarget {
|
|||
}
|
||||
|
||||
const createdAt = key.created_at || 0;
|
||||
const age = Date.now() - createdAt;
|
||||
if (age > ARCHIVE_AGE) {
|
||||
if (isOlderThan(createdAt, ARCHIVE_AGE)) {
|
||||
window.log.info(
|
||||
'Removing unconfirmed signed prekey:',
|
||||
key.keyId,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { isMoreRecentThan } from './timestamp';
|
||||
|
||||
const SIX_HOURS = 1000 * 60 * 60 * 6;
|
||||
|
||||
export function isConversationUnregistered({
|
||||
|
@ -8,6 +10,6 @@ export function isConversationUnregistered({
|
|||
}: Readonly<{ discoveredUnregisteredAt?: number }>): boolean {
|
||||
return Boolean(
|
||||
discoveredUnregisteredAt &&
|
||||
discoveredUnregisteredAt > Date.now() - SIX_HOURS
|
||||
isMoreRecentThan(discoveredUnregisteredAt, SIX_HOURS)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -14026,7 +14026,7 @@
|
|||
"rule": "jQuery-load(",
|
||||
"path": "ts/LibSignalStore.js",
|
||||
"line": " await window.ConversationController.load();",
|
||||
"lineNumber": 810,
|
||||
"lineNumber": 811,
|
||||
"reasonCategory": "falseMatch",
|
||||
"updated": "2021-02-27T00:48:49.313Z"
|
||||
},
|
||||
|
@ -14034,7 +14034,7 @@
|
|||
"rule": "jQuery-load(",
|
||||
"path": "ts/LibSignalStore.ts",
|
||||
"line": " await window.ConversationController.load();",
|
||||
"lineNumber": 1221,
|
||||
"lineNumber": 1222,
|
||||
"reasonCategory": "falseMatch",
|
||||
"updated": "2021-02-27T00:48:49.313Z"
|
||||
},
|
||||
|
|
10
ts/util/timestamp.ts
Normal file
10
ts/util/timestamp.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
export function isMoreRecentThan(timestamp: number, delta: number): boolean {
|
||||
return timestamp > Date.now() - delta;
|
||||
}
|
||||
|
||||
export function isOlderThan(timestamp: number, delta: number): boolean {
|
||||
return timestamp <= Date.now() - delta;
|
||||
}
|
Loading…
Reference in a new issue