Skip to content

Commit 0631bdc

Browse files
committed
userSelectors: Add getDisplayEmailForUser
Add function that gives users real email address, if known for displaying in the UI. Returns null if the user isn't able to see this users real email address. Add tests for above function.
1 parent d187aa3 commit 0631bdc

File tree

3 files changed

+71
-2
lines changed

3 files changed

+71
-2
lines changed

src/api/modelTypes.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,14 @@ export type User = {|
177177
// Current to feature level (FL) 121.
178178

179179
+user_id: UserId,
180-
+delivery_email?: string,
180+
181+
// Currently `delivery_email` is always `string` if present. A planned
182+
// future API may make it sometimes `null`, to explicitly indicate that no
183+
// delivery email for this user is visible to us:
184+
// https://chat.zulip.org/#narrow/stream/378-api-design/topic/email.20address.20visibility/near/1296132
185+
+delivery_email?: string | null,
181186
+email: string,
187+
182188
+full_name: string,
183189

184190
// We expect ISO 8601; that's in the doc's example response.
@@ -263,7 +269,7 @@ export type CrossRealmBot = {|
263269
// Current to feature level (FL) 121.
264270

265271
+user_id: UserId,
266-
+delivery_email?: string,
272+
+delivery_email?: string | null,
267273
+email: string,
268274
+full_name: string,
269275

src/users/__tests__/userSelectors-test.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import {
66
getUserForId,
77
getUserIsActive,
88
getCustomProfileFieldsForUser,
9+
getDisplayEmailForUser,
910
} from '../userSelectors';
1011
import * as eg from '../../__tests__/lib/exampleData';
1112
import { CustomProfileFieldType } from '../../api/modelTypes';
1213
import { randInt, randString } from '../../utils/misc';
14+
import { EmailAddressVisibility } from '../../api/permissionsTypes';
1315

1416
describe('getAllUsersByEmail', () => {
1517
test('return users mapped by their email', () => {
@@ -290,3 +292,45 @@ describe('getCustomProfileFieldsForUser', () => {
290292
).toMatchObject([{ fieldId: 1 }, { fieldId: 3 }]);
291293
});
292294
});
295+
296+
describe('getDisplayEmailForUser', () => {
297+
const mkUser = fields => ({ ...eg.otherUser, ...fields });
298+
299+
test('visibility is admin, no delivery_email', () => {
300+
const realm = eg.realmState({ emailAddressVisibility: EmailAddressVisibility.Admins });
301+
// eslint-disable-next-line no-unused-vars
302+
const { delivery_email, ...user } = eg.otherUser;
303+
expect(getDisplayEmailForUser(realm, user)).toBeNull();
304+
});
305+
306+
test('email visibility is everyone, no delivery_email', () => {
307+
const realm = eg.realmState({ emailAddressVisibility: EmailAddressVisibility.Everyone });
308+
// eslint-disable-next-line no-unused-vars
309+
const { delivery_email, ...user } = eg.otherUser;
310+
expect(getDisplayEmailForUser(realm, user)).toEqual(eg.otherUser.email);
311+
});
312+
313+
test('email visibility is everyone, delivery_email is null', () => {
314+
const realm = eg.realmState({ emailAddressVisibility: EmailAddressVisibility.Everyone });
315+
const user = mkUser({ delivery_email: null });
316+
expect(getDisplayEmailForUser(realm, user)).toBeNull();
317+
});
318+
319+
test('email visibility is everyone, delivery_email is set', () => {
320+
const realm = eg.realmState({ emailAddressVisibility: EmailAddressVisibility.Everyone });
321+
const user = mkUser({
322+
delivery_email: '[email protected]',
323+
324+
});
325+
expect(getDisplayEmailForUser(realm, user)).toEqual('[email protected]');
326+
});
327+
328+
test('email visibility is admins, delivery_email is set', () => {
329+
const realm = eg.realmState({ emailAddressVisibility: EmailAddressVisibility.Admins });
330+
const user = mkUser({
331+
delivery_email: '[email protected]',
332+
333+
});
334+
expect(getDisplayEmailForUser(realm, user)).toEqual('[email protected]');
335+
});
336+
});

src/users/userSelectors.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type { RealmState } from '../reduxTypes';
1313
import { getUsers, getCrossRealmBots, getNonActiveUsers } from '../directSelectors';
1414
import * as logging from '../utils/logging';
1515
import { ensureUnreachable } from '../generics';
16+
import { EmailAddressVisibility } from '../api/permissionsTypes';
1617

1718
/**
1819
* All users in this Zulip org (aka realm).
@@ -308,3 +309,21 @@ export function getCustomProfileFieldsForUser(
308309
}
309310
return fields;
310311
}
312+
313+
/**
314+
* The given user's real email address, if known, for displaying in the UI.
315+
*
316+
* Null if our user isn't able to see this user's real email address.
317+
*/
318+
export function getDisplayEmailForUser(realm: RealmState, user: UserOrBot): string | null {
319+
if (user.delivery_email !== undefined) {
320+
return user.delivery_email;
321+
} else if (realm.emailAddressVisibility === EmailAddressVisibility.Everyone) {
322+
// On future servers, we expect this case will never happen: we'll always include
323+
// a delivery_email when you have access, including when the visibility is Everyone
324+
// https://github.com/zulip/zulip-mobile/pull/5515#discussion_r997731727
325+
return user.email;
326+
} else {
327+
return null;
328+
}
329+
}

0 commit comments

Comments
 (0)