-
-
Notifications
You must be signed in to change notification settings - Fork 673
notification: Use user_id to find account if multiple on same realm #5108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
0621ff3
android notif [nfc]: Comment on when realm_uri was added in Identity
chrisbobbe 1f0cb71
notification types [nfc]: Factor `NotificationBase` out of `Notificat…
chrisbobbe ef05b47
notification tests: Fix a bug in baseline test for very-old-style mes…
chrisbobbe 28ccd7a
ios notif: Validate type of user_id field, when present
chrisbobbe aebde42
android notif [nfc]: Remove a redundant `let`
chrisbobbe 77ee121
ios notif [nfc]: Pull out `const identity` for realm_uri, and soon us…
chrisbobbe f405e0f
notif: Expose payload's user_id to inner code, when present
chrisbobbe 15783d6
notification tests [nfc]: Add a TODO for structuring tests more sensibly
chrisbobbe 84dfcdd
notif [nfc]: Give getAccountFromNotificationData accounts, not identi…
chrisbobbe b3e24ed
notification: Use user_id to find account if multiple on same realm
chrisbobbe File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ import { fromAPNsImpl as extractIosNotificationData } from '../extract'; | |
import objectEntries from '../../utils/objectEntries'; | ||
|
||
const realm_uri = eg.realm.toString(); | ||
const user_id = eg.selfUser.user_id; | ||
|
||
describe('getNarrowFromNotificationData', () => { | ||
const ownUserId = eg.selfUser.user_id; | ||
|
@@ -81,6 +82,14 @@ describe('extract iOS notification data', () => { | |
const msg = data; | ||
expect(verify(msg)).toEqual(msg); | ||
|
||
// new(-ish) optional user_id is accepted and copied | ||
// TODO: Rewrite so modern-style payloads are the baseline, e.g., | ||
// with a `modern` variable instead of `barebones`. Write | ||
// individual tests for supporting older-style payloads, and mark | ||
// those for future deletion, like with `TODO(1.9.0)`. | ||
const msg1 = { ...msg, user_id }; | ||
expect(verify(msg1)).toEqual(msg1); | ||
|
||
// unused fields are not copied | ||
const msg2 = { ...msg, realm_id: 8675309 }; | ||
expect(verify(msg2)).toEqual(msg); | ||
|
@@ -107,7 +116,7 @@ describe('extract iOS notification data', () => { | |
test('very-old-style messages', () => { | ||
const sender_email = '[email protected]'; | ||
// baseline | ||
expect(make({ realm_uri, recipient_type: 'private', sender_email })).toBeTruthy(); | ||
expect(make({ realm_uri, recipient_type: 'private', sender_email })()).toBeTruthy(); | ||
// missing recipient_type | ||
expect(make({ realm_uri, sender_email })).toThrow(/archaic/); | ||
// missing realm_uri | ||
|
@@ -155,6 +164,13 @@ describe('extract iOS notification data', () => { | |
realm_uri: ['array', 'of', 'string'], | ||
}), | ||
).toThrow(/invalid/); | ||
|
||
expect( | ||
make({ | ||
...barebones.stream, | ||
user_id: 'abc', | ||
}), | ||
).toThrow(/invalid/); | ||
}); | ||
|
||
test('hypothetical future: different event types', () => { | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ import PushNotificationIOS from '@react-native-community/push-notification-ios'; | |
import type { PushNotificationEventName } from '@react-native-community/push-notification-ios'; | ||
|
||
import type { Notification } from './types'; | ||
import type { Auth, Dispatch, GlobalDispatch, Identity, Narrow, UserId, UserOrBot } from '../types'; | ||
import type { Auth, Dispatch, GlobalDispatch, Account, Narrow, UserId, UserOrBot } from '../types'; | ||
import { topicNarrow, pm1to1NarrowFromUser, pmNarrowFromRecipients } from '../utils/narrow'; | ||
import type { JSONable, JSONableDict } from '../utils/jsonable'; | ||
import * as api from '../api'; | ||
|
@@ -25,16 +25,16 @@ import { getAccounts } from '../directSelectors'; | |
/** | ||
* Identify the account the notification is for, if possible. | ||
* | ||
* Returns an index into `identities`, or `null` if we can't tell. | ||
* Returns an index into `accounts`, or `null` if we can't tell. | ||
* In the latter case, logs a warning. | ||
* | ||
* @param identities Identities corresponding to the accounts state in Redux. | ||
* @param accounts The accounts state in Redux. | ||
*/ | ||
export const getAccountFromNotificationData = ( | ||
data: Notification, | ||
identities: $ReadOnlyArray<Identity>, | ||
accounts: $ReadOnlyArray<Account>, | ||
): number | null => { | ||
const { realm_uri } = data; | ||
const { realm_uri, user_id } = data; | ||
if (realm_uri == null) { | ||
// Old server, no realm info included. If needed to cater to 1.8.x | ||
// servers, could try to guess using serverHost; for now, don't. | ||
|
@@ -50,7 +50,7 @@ export const getAccountFromNotificationData = ( | |
} | ||
|
||
const urlMatches = []; | ||
identities.forEach((account, i) => { | ||
accounts.forEach((account, i) => { | ||
if (account.realm.origin === realmUrl.origin) { | ||
urlMatches.push(i); | ||
} | ||
|
@@ -62,7 +62,7 @@ export const getAccountFromNotificationData = ( | |
// just a race -- this notification was sent before the logout); or | ||
// there's some confusion where the realm_uri we have is different from | ||
// the one the server sends in notifications. | ||
const knownUrls = identities.map(({ realm }) => realm.href); | ||
const knownUrls = accounts.map(({ realm }) => realm.href); | ||
logging.warn('notification realm_uri not found in accounts', { | ||
realm_uri, | ||
parsed_url: realmUrl, | ||
|
@@ -71,23 +71,50 @@ export const getAccountFromNotificationData = ( | |
return null; | ||
} | ||
|
||
if (urlMatches.length > 1) { | ||
// The user has several accounts in the notification's realm. We should | ||
// be able to tell the right one using the notification's `user_id`... | ||
// except we don't store user IDs in `accounts`, only emails. Until we | ||
// fix that, just ignore the information. | ||
logging.warn('notification realm_uri ambiguous; multiple matches found', { | ||
realm_uri, | ||
parsed_url: realmUrl, | ||
match_count: urlMatches.length, | ||
unique_identities_count: new Set(urlMatches.map(matchIndex => identities[matchIndex].email)) | ||
.size, | ||
}); | ||
// TODO get user_id into accounts data, and use that | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: this TODO comment should go away in the later commit where we start using the user_id |
||
return null; | ||
// TODO(server-2.1): Remove this, because user_id will always be present | ||
if (user_id === undefined) { | ||
if (urlMatches.length > 1) { | ||
logging.warn( | ||
'notification realm_uri ambiguous; multiple matches found; user_id missing (old server)', | ||
{ | ||
realm_uri, | ||
parsed_url: realmUrl, | ||
match_count: urlMatches.length, | ||
unique_identities_count: new Set(urlMatches.map(matchIndex => accounts[matchIndex].email)) | ||
.size, | ||
}, | ||
); | ||
return null; | ||
} else { | ||
return urlMatches[0]; | ||
} | ||
} | ||
|
||
return urlMatches[0]; | ||
// There may be multiple accounts in the notification's realm. Pick one | ||
// based on the notification's `user_id`. | ||
const userMatch = urlMatches.find(urlMatch => accounts[urlMatch].userId === user_id); | ||
if (userMatch == null) { | ||
// Maybe we didn't get a userId match because the correct account just | ||
// hasn't had its userId recorded on it yet. See jsdoc on the Account | ||
// type for when that is. | ||
const nullUserIdMatches = urlMatches.filter(urlMatch => accounts[urlMatch].userId === null); | ||
switch (nullUserIdMatches.length) { | ||
case 0: | ||
logging.warn( | ||
'notifications: No accounts found with matching realm and matching-or-null user ID', | ||
); | ||
return null; | ||
case 1: | ||
return nullUserIdMatches[0]; | ||
default: | ||
logging.warn( | ||
'notifications: Multiple accounts found with matching realm and null user ID; could not choose', | ||
{ nullUserIdMatchesCount: nullUserIdMatches.length }, | ||
); | ||
return null; | ||
} | ||
} | ||
return userMatch; | ||
}; | ||
|
||
export const getNarrowFromNotificationData = ( | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oof. The
Auth
does of course have the email. So anywhere we have an Auth and can't readily make an Identity, because we lack the user ID, is an obstacle to converting from emails to IDs, #3764.In
authFromCallbackUrl
, we're decoding one of thosezulip://
URLs the server used to complete a web login and get us the API key. So we should get the server to start giving us user IDs there, even if we won't be able to count on their presence for a while. That should be a thread in#api design
, then.