mirror of https://github.com/zulip/zulip.git
people: Make `get_by_user_id` type-safe.
We should make `get_by_user_id` type-safe in the sense that it's caller should not expect undefined values and hence it's caller should not need to validate the user ids. To do this I extracted a method `maybe_get_user_by_id` which is type-unsafe version of this function which will allow undefined values and will behave exactly the same as the previous version. So the callers which expects the undefined values from this function should use this new function `maybe_get_user_by_id`. Probably about half of these callers are implicitly iterating through all users in the people.js data set and thus by construction should never fail, but it's simpler to just convert all existing callers than do that audit.
This commit is contained in:
parent
9b0e7a3eae
commit
1c8bf4f050
|
@ -75,8 +75,8 @@ export function compare_function(a, b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort equivalent direct message names alphabetically
|
// Sort equivalent direct message names alphabetically
|
||||||
const person_a = people.get_by_user_id(a);
|
const person_a = people.maybe_get_user_by_id(a);
|
||||||
const person_b = people.get_by_user_id(b);
|
const person_b = people.maybe_get_user_by_id(b);
|
||||||
|
|
||||||
const full_name_a = person_a ? person_a.full_name : "";
|
const full_name_a = person_a ? person_a.full_name : "";
|
||||||
const full_name_b = person_b ? person_b.full_name : "";
|
const full_name_b = person_b ? person_b.full_name : "";
|
||||||
|
@ -253,7 +253,7 @@ function filter_user_ids(user_filter_text, user_ids) {
|
||||||
// This first filter is for whether the user is eligible to be
|
// This first filter is for whether the user is eligible to be
|
||||||
// displayed in the right sidebar at all.
|
// displayed in the right sidebar at all.
|
||||||
user_ids = user_ids.filter((user_id) => {
|
user_ids = user_ids.filter((user_id) => {
|
||||||
const person = people.get_by_user_id(user_id);
|
const person = people.maybe_get_user_by_id(user_id);
|
||||||
|
|
||||||
if (!person) {
|
if (!person) {
|
||||||
blueslip.warn("Got user_id in presence but not people: " + user_id);
|
blueslip.warn("Got user_id in presence but not people: " + user_id);
|
||||||
|
|
|
@ -39,7 +39,7 @@ export function needs_subscribe_warning(user_id, stream_id) {
|
||||||
// We expect the caller to already have verified that we're
|
// We expect the caller to already have verified that we're
|
||||||
// sending to a valid stream and trying to mention the user.
|
// sending to a valid stream and trying to mention the user.
|
||||||
|
|
||||||
const user = people.get_by_user_id(user_id);
|
const user = people.maybe_get_user_by_id(user_id);
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -29,7 +29,7 @@ export function process_new_message(message) {
|
||||||
people.extract_people_from_message(message);
|
people.extract_people_from_message(message);
|
||||||
people.maybe_incr_recipient_count(message);
|
people.maybe_incr_recipient_count(message);
|
||||||
|
|
||||||
const sender = people.get_by_user_id(message.sender_id);
|
const sender = people.maybe_get_user_by_id(message.sender_id);
|
||||||
if (sender) {
|
if (sender) {
|
||||||
message.sender_full_name = sender.full_name;
|
message.sender_full_name = sender.full_name;
|
||||||
message.sender_email = sender.email;
|
message.sender_email = sender.email;
|
||||||
|
|
|
@ -39,7 +39,7 @@ export function get_pm_emails(message) {
|
||||||
const user_ids = people.pm_with_user_ids(message);
|
const user_ids = people.pm_with_user_ids(message);
|
||||||
const emails = user_ids
|
const emails = user_ids
|
||||||
.map((user_id) => {
|
.map((user_id) => {
|
||||||
const person = people.get_by_user_id(user_id);
|
const person = people.maybe_get_user_by_id(user_id);
|
||||||
if (!person) {
|
if (!person) {
|
||||||
blueslip.error("Unknown user id", {user_id});
|
blueslip.error("Unknown user id", {user_id});
|
||||||
return "?";
|
return "?";
|
||||||
|
|
|
@ -98,7 +98,7 @@ export function add_subscriber(stream_id, user_id) {
|
||||||
// If stream_id/user_id are unknown to us, we will
|
// If stream_id/user_id are unknown to us, we will
|
||||||
// still track it, but we will warn.
|
// still track it, but we will warn.
|
||||||
const subscribers = get_user_set(stream_id);
|
const subscribers = get_user_set(stream_id);
|
||||||
const person = people.get_by_user_id(user_id);
|
const person = people.maybe_get_user_by_id(user_id);
|
||||||
if (person === undefined) {
|
if (person === undefined) {
|
||||||
blueslip.warn("We tried to add invalid subscriber: " + user_id);
|
blueslip.warn("We tried to add invalid subscriber: " + user_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import md5 from "blueimp-md5";
|
import md5 from "blueimp-md5";
|
||||||
import {format, utcToZonedTime} from "date-fns-tz";
|
import {format, utcToZonedTime} from "date-fns-tz";
|
||||||
|
import assert from "minimalistic-assert";
|
||||||
|
|
||||||
import * as typeahead from "../shared/src/typeahead";
|
import * as typeahead from "../shared/src/typeahead";
|
||||||
|
|
||||||
|
@ -58,9 +59,17 @@ export function get_users_from_ids(user_ids) {
|
||||||
return user_ids.map((user_id) => get_by_user_id(user_id));
|
return user_ids.map((user_id) => get_by_user_id(user_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_by_user_id(user_id, ignore_missing) {
|
// Use this function only when you are sure that user_id is valid.
|
||||||
if (!people_by_user_id_dict.has(user_id) && !ignore_missing) {
|
export function get_by_user_id(user_id) {
|
||||||
blueslip.error("Unknown user_id in get_by_user_id", {user_id});
|
const person = people_by_user_id_dict.get(user_id);
|
||||||
|
assert(person, `Unknown user_id in get_by_user_id: ${user_id}`);
|
||||||
|
return person;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is type unsafe version of get_by_user_id for the callers that expects undefined values.
|
||||||
|
export function maybe_get_user_by_id(user_id) {
|
||||||
|
if (!people_by_user_id_dict.has(user_id)) {
|
||||||
|
blueslip.error("Unknown user_id in maybe_get_user_by_id", {user_id});
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return people_by_user_id_dict.get(user_id);
|
return people_by_user_id_dict.get(user_id);
|
||||||
|
@ -347,7 +356,7 @@ export function get_full_names_for_poll_option(user_ids) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_display_full_name(user_id) {
|
export function get_display_full_name(user_id) {
|
||||||
const person = get_by_user_id(user_id);
|
const person = maybe_get_user_by_id(user_id);
|
||||||
if (!person) {
|
if (!person) {
|
||||||
blueslip.error("Unknown user id", {user_id});
|
blueslip.error("Unknown user id", {user_id});
|
||||||
return "?";
|
return "?";
|
||||||
|
@ -528,7 +537,7 @@ export function pm_with_url(message) {
|
||||||
if (user_ids.length > 1) {
|
if (user_ids.length > 1) {
|
||||||
suffix = "group";
|
suffix = "group";
|
||||||
} else {
|
} else {
|
||||||
const person = get_by_user_id(user_ids[0]);
|
const person = maybe_get_user_by_id(user_ids[0]);
|
||||||
if (person && person.full_name) {
|
if (person && person.full_name) {
|
||||||
suffix = person.full_name.replaceAll(/[ "%/<>`\p{C}]+/gu, "-");
|
suffix = person.full_name.replaceAll(/[ "%/<>`\p{C}]+/gu, "-");
|
||||||
} else {
|
} else {
|
||||||
|
@ -772,7 +781,7 @@ export function small_avatar_url(message) {
|
||||||
// We should always have message.sender_id, except for in the
|
// We should always have message.sender_id, except for in the
|
||||||
// tutorial, where it's ok to fall back to the URL in the fake
|
// tutorial, where it's ok to fall back to the URL in the fake
|
||||||
// messages.
|
// messages.
|
||||||
person = get_by_user_id(message.sender_id);
|
person = maybe_get_user_by_id(message.sender_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The first time we encounter a sender in a message, we may
|
// The first time we encounter a sender in a message, we may
|
||||||
|
|
|
@ -450,7 +450,7 @@ function get_user_info_popover_manage_menu_items() {
|
||||||
|
|
||||||
function fetch_group_members(member_ids) {
|
function fetch_group_members(member_ids) {
|
||||||
return member_ids
|
return member_ids
|
||||||
.map((m) => people.get_by_user_id(m))
|
.map((m) => people.maybe_get_user_by_id(m))
|
||||||
.filter((m) => m !== undefined)
|
.filter((m) => m !== undefined)
|
||||||
.map((p) => ({
|
.map((p) => ({
|
||||||
...p,
|
...p,
|
||||||
|
|
|
@ -175,7 +175,7 @@ export function set_info(presences, server_timestamp) {
|
||||||
// reload_state.is_in_progress, because races where presence
|
// reload_state.is_in_progress, because races where presence
|
||||||
// returns data on users not yet received via the server_events
|
// returns data on users not yet received via the server_events
|
||||||
// system are common in both situations.
|
// system are common in both situations.
|
||||||
const person = people.get_by_user_id(user_id, true);
|
const person = people.maybe_get_user_by_id(user_id);
|
||||||
if (person === undefined) {
|
if (person === undefined) {
|
||||||
if (!(watchdog.suspects_user_is_offline() || reload_state.is_in_progress())) {
|
if (!(watchdog.suspects_user_is_offline() || reload_state.is_in_progress())) {
|
||||||
// If we're online, and we get a user who we don't
|
// If we're online, and we get a user who we don't
|
||||||
|
|
|
@ -107,7 +107,7 @@ export const update_elements = ($content) => {
|
||||||
// mention text to show the user's current name,
|
// mention text to show the user's current name,
|
||||||
// assuming that you're not searching for text
|
// assuming that you're not searching for text
|
||||||
// inside the highlight.
|
// inside the highlight.
|
||||||
const person = people.get_by_user_id(user_id, true);
|
const person = people.maybe_get_user_by_id(user_id);
|
||||||
if (person !== undefined) {
|
if (person !== undefined) {
|
||||||
// Note that person might be undefined in some
|
// Note that person might be undefined in some
|
||||||
// unpleasant corner cases involving data import.
|
// unpleasant corner cases involving data import.
|
||||||
|
|
|
@ -340,7 +340,7 @@ export function confirm_bot_deactivation(bot_id, handle_confirm, loading_spinner
|
||||||
}
|
}
|
||||||
|
|
||||||
export function show_edit_bot_info_modal(user_id, from_user_info_popover) {
|
export function show_edit_bot_info_modal(user_id, from_user_info_popover) {
|
||||||
const bot = people.get_by_user_id(user_id);
|
const bot = people.maybe_get_user_by_id(user_id);
|
||||||
const owner_id = bot_data.get(user_id).owner_id;
|
const owner_id = bot_data.get(user_id).owner_id;
|
||||||
const owner_full_name = people.get_full_name(owner_id);
|
const owner_full_name = people.get_full_name(owner_id);
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ export function populate_emoji() {
|
||||||
for (const emoji of Object.values(emoji_data)) {
|
for (const emoji of Object.values(emoji_data)) {
|
||||||
// Add people.js data for the user here.
|
// Add people.js data for the user here.
|
||||||
if (emoji.author_id !== null) {
|
if (emoji.author_id !== null) {
|
||||||
emoji.author = people.get_by_user_id(emoji.author_id);
|
emoji.author = people.maybe_get_user_by_id(emoji.author_id);
|
||||||
} else {
|
} else {
|
||||||
emoji.author = null;
|
emoji.author = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,7 +191,7 @@ function bot_owner_full_name(owner_id) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bot_owner = people.get_by_user_id(owner_id);
|
const bot_owner = people.maybe_get_user_by_id(owner_id);
|
||||||
if (!bot_owner) {
|
if (!bot_owner) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ function bot_owner_full_name(owner_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function bot_info(bot_user_id) {
|
function bot_info(bot_user_id) {
|
||||||
const bot_user = people.get_by_user_id(bot_user_id);
|
const bot_user = people.maybe_get_user_by_id(bot_user_id);
|
||||||
|
|
||||||
if (!bot_user) {
|
if (!bot_user) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
@ -616,7 +616,7 @@ function handle_reactivation($tbody) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function show_edit_user_info_modal(user_id, from_user_info_popover) {
|
export function show_edit_user_info_modal(user_id, from_user_info_popover) {
|
||||||
const person = people.get_by_user_id(user_id);
|
const person = people.maybe_get_user_by_id(user_id);
|
||||||
|
|
||||||
if (!person) {
|
if (!person) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -40,7 +40,7 @@ export function must_be_subscribed(user_id) {
|
||||||
export function add_user_ids(user_ids) {
|
export function add_user_ids(user_ids) {
|
||||||
for (const user_id of user_ids) {
|
for (const user_id of user_ids) {
|
||||||
if (!user_id_set.has(user_id)) {
|
if (!user_id_set.has(user_id)) {
|
||||||
const user = people.get_by_user_id(user_id);
|
const user = people.maybe_get_user_by_id(user_id);
|
||||||
if (user) {
|
if (user) {
|
||||||
user_id_set.add(user_id);
|
user_id_set.add(user_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ import * as settings_streams from "./settings_streams";
|
||||||
import * as settings_users from "./settings_users";
|
import * as settings_users from "./settings_users";
|
||||||
|
|
||||||
export const update_person = function update(person) {
|
export const update_person = function update(person) {
|
||||||
const person_obj = people.get_by_user_id(person.user_id);
|
const person_obj = people.maybe_get_user_by_id(person.user_id);
|
||||||
|
|
||||||
if (!person_obj) {
|
if (!person_obj) {
|
||||||
blueslip.error("Got update_person event for unexpected user", {user_id: person.user_id});
|
blueslip.error("Got update_person event for unexpected user", {user_id: person.user_id});
|
||||||
|
|
|
@ -36,7 +36,7 @@ export function get_potential_members() {
|
||||||
export function add_user_ids(user_ids) {
|
export function add_user_ids(user_ids) {
|
||||||
for (const user_id of user_ids) {
|
for (const user_id of user_ids) {
|
||||||
if (!user_id_set.has(user_id)) {
|
if (!user_id_set.has(user_id)) {
|
||||||
const user = people.get_by_user_id(user_id);
|
const user = people.maybe_get_user_by_id(user_id);
|
||||||
if (user) {
|
if (user) {
|
||||||
user_id_set.add(user_id);
|
user_id_set.add(user_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -549,7 +549,7 @@ test("get_items_for_users", () => {
|
||||||
|
|
||||||
test("error handling", () => {
|
test("error handling", () => {
|
||||||
presence.presence_info.set(42, {status: "active"});
|
presence.presence_info.set(42, {status: "active"});
|
||||||
blueslip.expect("error", "Unknown user_id in get_by_user_id");
|
blueslip.expect("error", "Unknown user_id in maybe_get_user_by_id");
|
||||||
blueslip.expect("warn", "Got user_id in presence but not people: 42");
|
blueslip.expect("warn", "Got user_id in presence but not people: 42");
|
||||||
buddy_data.get_filtered_and_sorted_user_ids();
|
buddy_data.get_filtered_and_sorted_user_ids();
|
||||||
});
|
});
|
||||||
|
|
|
@ -616,7 +616,7 @@ test_ui("needs_subscribe_warning", () => {
|
||||||
stream_data.add_sub(sub);
|
stream_data.add_sub(sub);
|
||||||
peer_data.set_subscribers(sub.stream_id, [bob.user_id, me.user_id]);
|
peer_data.set_subscribers(sub.stream_id, [bob.user_id, me.user_id]);
|
||||||
|
|
||||||
blueslip.expect("error", "Unknown user_id in get_by_user_id");
|
blueslip.expect("error", "Unknown user_id in maybe_get_user_by_id");
|
||||||
// Test with an invalid user id.
|
// Test with an invalid user id.
|
||||||
assert.equal(compose_validate.needs_subscribe_warning(invalid_user_id, sub.stream_id), false);
|
assert.equal(compose_validate.needs_subscribe_warning(invalid_user_id, sub.stream_id), false);
|
||||||
|
|
||||||
|
|
|
@ -212,7 +212,7 @@ test("errors", ({disallow_rewire}) => {
|
||||||
display_recipient: [{id: 92714}],
|
display_recipient: [{id: 92714}],
|
||||||
};
|
};
|
||||||
|
|
||||||
blueslip.expect("error", "Unknown user_id in get_by_user_id", 2);
|
blueslip.expect("error", "Unknown user_id in maybe_get_user_by_id", 2);
|
||||||
blueslip.expect("error", "Unknown user id", 2); // From person.js
|
blueslip.expect("error", "Unknown user id", 2); // From person.js
|
||||||
|
|
||||||
// Expect each to throw two blueslip errors
|
// Expect each to throw two blueslip errors
|
||||||
|
|
|
@ -204,7 +204,7 @@ test("subscribers", () => {
|
||||||
blueslip.reset();
|
blueslip.reset();
|
||||||
|
|
||||||
// Verify that we don't crash for a bad user id.
|
// Verify that we don't crash for a bad user id.
|
||||||
blueslip.expect("error", "Unknown user_id in get_by_user_id");
|
blueslip.expect("error", "Unknown user_id in maybe_get_user_by_id");
|
||||||
blueslip.expect("warn", "We tried to add invalid subscriber: 88888");
|
blueslip.expect("warn", "We tried to add invalid subscriber: 88888");
|
||||||
peer_data.add_subscriber(stream_id, 88888);
|
peer_data.add_subscriber(stream_id, 88888);
|
||||||
blueslip.reset();
|
blueslip.reset();
|
||||||
|
|
|
@ -795,7 +795,7 @@ test_people("message_methods", () => {
|
||||||
"https://secure.gravatar.com/avatar/6dbdd7946b58d8b11351fcb27e5cdd55?d=identicon&s=50",
|
"https://secure.gravatar.com/avatar/6dbdd7946b58d8b11351fcb27e5cdd55?d=identicon&s=50",
|
||||||
);
|
);
|
||||||
|
|
||||||
blueslip.expect("error", "Unknown user_id in get_by_user_id");
|
blueslip.expect("error", "Unknown user_id in maybe_get_user_by_id");
|
||||||
message = {
|
message = {
|
||||||
avatar_url: undefined,
|
avatar_url: undefined,
|
||||||
sender_email: "foo@example.com",
|
sender_email: "foo@example.com",
|
||||||
|
|
|
@ -101,7 +101,7 @@ run_test("blueslip", () => {
|
||||||
const reply_to = people.pm_reply_to(message);
|
const reply_to = people.pm_reply_to(message);
|
||||||
assert.ok(reply_to.includes("?"));
|
assert.ok(reply_to.includes("?"));
|
||||||
|
|
||||||
blueslip.expect("error", "Unknown user_id in get_by_user_id");
|
blueslip.expect("error", "Unknown user_id in maybe_get_user_by_id");
|
||||||
blueslip.expect("error", "Unknown people in message");
|
blueslip.expect("error", "Unknown people in message");
|
||||||
const url = people.pm_with_url({type: "private", display_recipient: [{id: 42}]});
|
const url = people.pm_with_url({type: "private", display_recipient: [{id: 42}]});
|
||||||
assert.equal(url.indexOf("unk"), url.length - 3);
|
assert.equal(url.indexOf("unk"), url.length - 3);
|
||||||
|
|
|
@ -95,6 +95,7 @@ test("unknown user", ({override}) => {
|
||||||
const presences = {};
|
const presences = {};
|
||||||
presences[unknown_user_id.toString()] = "does-not-matter";
|
presences[unknown_user_id.toString()] = "does-not-matter";
|
||||||
|
|
||||||
|
blueslip.expect("error", "Unknown user_id in maybe_get_user_by_id", 3);
|
||||||
blueslip.expect("error", "Unknown user ID in presence data");
|
blueslip.expect("error", "Unknown user ID in presence data");
|
||||||
presence.set_info(presences, now);
|
presence.set_info(presences, now);
|
||||||
|
|
||||||
|
|
|
@ -217,7 +217,7 @@ run_test("updates", () => {
|
||||||
assert.ok(person.timezone);
|
assert.ok(person.timezone);
|
||||||
|
|
||||||
blueslip.expect("error", "Got update_person event for unexpected user");
|
blueslip.expect("error", "Got update_person event for unexpected user");
|
||||||
blueslip.expect("error", "Unknown user_id in get_by_user_id");
|
blueslip.expect("error", "Unknown user_id in maybe_get_user_by_id");
|
||||||
assert.ok(!user_events.update_person({user_id: 29, full_name: "Sir Isaac Newton"}));
|
assert.ok(!user_events.update_person({user_id: 29, full_name: "Sir Isaac Newton"}));
|
||||||
|
|
||||||
me.profile_data = {};
|
me.profile_data = {};
|
||||||
|
|
Loading…
Reference in New Issue