FIX: Escape periods in current user's username before generating `RegExp` (#13247)

If we don't escape periods, they are interpreted as wildcards and it
becomes impossible to visit profiles of other users whose usernames
match. E.g., if your username was `a.c` and attempted to visit `abc`'s
profile, you would be incorrectly redirected to your own profile.
This commit is contained in:
Osama Sayegh 2021-06-03 07:15:38 +03:00 committed by GitHub
parent f3e021ad45
commit 3249312c81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 323 additions and 1 deletions

View File

@ -9,8 +9,9 @@ export default {
const currentUser = container.lookup("current-user:main");
if (currentUser) {
const username = currentUser.get("username");
const escapedUsername = username.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
DiscourseURL.rewrite(
new RegExp(`^/u/${username}/?$`, "i"),
new RegExp(`^/u/${escapedUsername}/?$`, "i"),
`/u/${username}/activity`
);
}

View File

@ -1,6 +1,7 @@
import {
acceptance,
exists,
query,
queryAll,
} from "discourse/tests/helpers/qunit-helpers";
import { click, currentRouteName, visit } from "@ember/test-helpers";
@ -97,3 +98,26 @@ acceptance("User Routes", function (needs) {
);
});
});
acceptance(
"User Routes - Periods in current user's username",
function (needs) {
needs.user({ username: "e.il.rout" });
test("Periods in current user's username don't act like wildcards", async function (assert) {
await visit("/u/eviltrout");
assert.equal(
query(".user-profile-names .username").textContent.trim(),
"eviltrout",
"eviltrout profile is shown"
);
await visit("/u/e.il.rout");
assert.equal(
query(".user-profile-names .username").textContent.trim(),
"e.il.rout",
"e.il.rout profile is shown"
);
});
}
);

View File

@ -3022,4 +3022,301 @@ export default {
top_categories: [],
},
},
"/u/e.il.rout.json": {
user_badges: [
{
id: 5870,
granted_at: "2014-05-16T02:39:38.388Z",
badge_id: 4,
user_id: 19,
granted_by_id: -1,
},
{
id: 40673,
granted_at: "2014-03-31T14:23:18.060Z",
post_id: 7241,
post_number: 19,
badge_id: 23,
user_id: 19,
granted_by_id: -1,
topic_id: 3153,
},
{
id: 5868,
granted_at: "2014-05-16T02:39:38.380Z",
badge_id: 3,
user_id: 19,
granted_by_id: -1,
},
],
badges: [
{
id: 4,
name: "Leader",
description: null,
grant_count: 7,
allow_title: true,
multiple_grant: false,
icon: "fa-user",
image: null,
listable: true,
enabled: true,
badge_grouping_id: 4,
system: true,
badge_type_id: 1,
},
{
id: 23,
name: "Great Share",
description: null,
grant_count: 14,
allow_title: false,
multiple_grant: true,
icon: "fa-certificate",
image: null,
listable: true,
enabled: true,
badge_grouping_id: 2,
system: true,
badge_type_id: 1,
},
{
id: 3,
name: "Regular",
description: null,
grant_count: 30,
allow_title: true,
multiple_grant: false,
icon: "fa-user",
image: null,
listable: true,
enabled: true,
badge_grouping_id: 4,
system: true,
badge_type_id: 2,
},
],
badge_types: [
{ id: 1, name: "Gold", sort_order: 9 },
{ id: 2, name: "Silver", sort_order: 8 },
{ id: 3, name: "Bronze", sort_order: 7 },
],
users: [
{
id: 19,
username: "eviltrout",
uploaded_avatar_id: null,
avatar_template:
"/letter_avatar/eviltrout/{size}/3_f9720745f5ce6dfc2b5641fca999d934.png",
},
{
id: -1,
username: "system",
uploaded_avatar_id: null,
avatar_template:
"/letter_avatar/system/{size}/3_f9720745f5ce6dfc2b5641fca999d934.png",
},
],
topics: [
{
id: 3153,
title: "Is it better for Discourse to use JavaScript or CoffeeScript?",
fancy_title:
"Is it better for Discourse to use JavaScript or CoffeeScript?",
slug: "is-it-better-for-discourse-to-use-javascript-or-coffeescript",
posts_count: 56,
},
],
user: {
user_option: {
text_size_seq: 1,
},
id: 4432,
username: "e.il.rout",
uploaded_avatar_id: null,
avatar_template:
"/letter_avatar/e.il.rout/{size}/3_f9720745f5ce6dfc2b5641fca999d934.png",
name: "Robin Ward",
email: "robin.ward@example.com",
associated_accounts: [
{
name: "facebook",
description: "robin.ward@example.com",
can_revoke: true,
},
],
last_posted_at: "2015-05-07T15:23:35.074Z",
last_seen_at: "2015-05-13T14:34:23.188Z",
bio_raw:
'Co-founder of Discourse. Previously, I created <a href="http://forumwarz.com">Forumwarz</a>. <a href="https://twitter.com/eviltrout">Follow me on Twitter</a>. I am @eviltrout.',
bio_cooked:
'<p>Co-founder of Discourse. Previously, I created <a href="http://forumwarz.com">Forumwarz</a>. <a href="https://twitter.com/eviltrout">Follow me on Twitter</a>. I am <a class="mention" href="/u/eviltrout">@eviltrout</a>.</p>',
created_at: "2013-02-03T15:19:22.704Z",
website: "http://eviltrout.com",
location: "Toronto",
can_edit: false,
can_edit_username: true,
can_edit_email: true,
can_edit_name: true,
stats: [
{ action_type: 13, count: 342, id: null },
{ action_type: 12, count: 109, id: null },
{ action_type: 4, count: 27, id: null },
{ action_type: 5, count: 1607, id: null },
{ action_type: 6, count: 771, id: null },
{ action_type: 1, count: 333, id: null },
{ action_type: 2, count: 2671, id: null },
{ action_type: 7, count: 949, id: null },
{ action_type: 9, count: 42, id: null },
{ action_type: 3, count: 8, id: null },
{ action_type: 11, count: 20, id: null },
],
can_send_private_messages: true,
can_send_private_message_to_user: false,
bio_excerpt:
'<p>Co-founder of Discourse. Previously, I created <a href="http://forumwarz.com">Forumwarz</a>. <a href="https://twitter.com/eviltrout">Follow me on Twitter</a>. I am <a class="mention" href="/u/eviltrout">@eviltrout</a>.</p>',
trust_level: 4,
moderator: true,
admin: true,
title: "co-founder",
badge_count: 23,
notification_count: 3244,
has_title_badges: true,
custom_fields: {},
user_fields: { 1: "33" },
pending_count: 0,
post_count: 1987,
can_be_deleted: false,
can_delete_all_posts: false,
locale: "",
email_digests: true,
email_messages_level: 0,
email_level: 1,
digest_after_minutes: 10080,
mailing_list_mode: false,
auto_track_topics_after_msecs: 60000,
new_topic_duration_minutes: 1440,
external_links_in_new_tab: false,
dynamic_favicon: true,
skip_new_user_tips: false,
enable_quoting: true,
muted_category_ids: [],
regular_category_ids: [],
tracked_category_ids: [],
watched_category_ids: [3],
watched_first_post_category_ids: [],
private_messages_stats: { all: 101, mine: 13, unread: 3 },
gravatar_avatar_upload_id: 5275,
custom_avatar_upload_id: 1573,
card_image_badge: "/images/avatar.png",
card_image_badge_id: 120,
muted_usernames: [],
can_change_location: true,
ignored_usernames: [],
invited_by: {
id: 1,
username: "sam",
uploaded_avatar_id: null,
avatar_template:
"/letter_avatar/sam/{size}/3_f9720745f5ce6dfc2b5641fca999d934.png",
},
custom_groups: [
{
id: 44,
automatic: false,
name: "ubuntu",
user_count: 11,
alias_level: 0,
visible: true,
automatic_membership_email_domains: null,
primary_group: false,
title: null,
},
{
id: 47,
automatic: false,
name: "discourse",
user_count: 7,
alias_level: 0,
visible: true,
automatic_membership_email_domains: null,
primary_group: false,
title: null,
},
],
featured_user_badge_ids: [5870, 40673, 5868],
card_badge: {
id: 120,
name: "Garbage Man",
description:
'This Discourse developer successfully called something "garbage!"',
grant_count: 3,
allow_title: false,
multiple_grant: false,
icon: "/images/avatar.png",
image: "/images/avatar.png",
listable: false,
enabled: false,
badge_grouping_id: 8,
system: false,
badge_type_id: 3,
},
user_auth_tokens: [
{
id: 2,
client_ip: "188.192.99.49",
location: "Augsburg, Bavaria, Germany",
browser: "Google Chrome",
device: "Linux Computer",
os: "Linux",
icon: "fab-linux",
created_at: "2018-09-08T21:22:56.225Z",
seen_at: "2018-09-08T21:22:56.512Z",
is_active: false,
},
{
id: 3,
client_ip: "188.120.223.89",
location: "České Budějovice, České Budějovice District, Czechia",
browser: "Google Chrome",
device: "Linux Computer",
os: "Linux",
icon: "fab-linux",
created_at: "2018-09-08T21:33:41.616Z",
seen_at: "2018-09-08T21:33:42.209Z",
is_active: true,
},
{
id: 6,
client_ip: "188.233.223.89",
location: "Tula, Tul'skaya Oblast, Russia",
browser: "Internet Explorer",
device: "Windows Computer",
os: "Windows",
icon: "fab-windows",
created_at: "2018-09-07T21:44:41.616Z",
seen_at: "2018-09-08T21:44:42.209Z",
is_active: false,
},
],
user_notification_schedule: {
enabled: false,
day_0_start_time: 480,
day_0_end_time: 1020,
day_1_start_time: 480,
day_1_end_time: 1020,
day_2_start_time: 480,
day_2_end_time: 1020,
day_3_start_time: 480,
day_3_end_time: 1020,
day_4_start_time: 480,
day_4_end_time: 1020,
day_5_start_time: 480,
day_5_end_time: 1020,
day_6_start_time: 480,
day_6_end_time: 1020,
},
timezone: "Australia/Brisbane",
},
},
};