thoka
(Thomas Kalka)
22.Апрель.2026 19:47:26
1
При исследовании Private Topics Plugin - #109 by thoka я обнаружил, что упоминание пользователя в ограниченной категории не фиксируется, если имя пользователя содержит заглавные буквы.
Если я упоминаю @SomeUser, редактор отправляет запрос
/composer/mentions.json?names[]=SomeUser&topic_id=10728,
и в результате возвращается имя пользователя в нижнем регистре, без установки user_reasons.
Запрос имени пользователя в нижнем регистре возвращает "user_reasons": {"someuser":"category"}.
Если в редакторе использовать имена пользователей в нижнем регистре, будут отображаться предупреждения для пользователей с недостаточными правами.
Если использовать автодополнение, предоставляемое редактором, введённые имена в нижнем регистре заменяются на имена с заглавными буквами, и поэтому они не фиксируются.
3 лайка
RGJ
(Richard - Communiteq)
22.Апрель.2026 21:26:53
2
Отличная находка, @thoka !
Проблема здесь:
users возвращает {"username_lower" => объект User }.
Однако, если name не приведен к нижнему регистру, users[name] не существует.
Исправление:
if user = users[name.downcase]
...
elsif group = groups[name.downcase]
...
Или ещё лучше: приведите все имена к нижнему регистру в начале метода, так как там много проблем. groups корректно использует .where("lower(name) IN (?)", @names.map(&:downcase)), но функции visible_group_ids_for_allowed_check, topic_allowed_group_ids, mentionable_group_ids и members_visible_group_ids все используют where(name: @names), что также вносит проблемы с чувствительностью к регистру.
3 лайка
Правильное исправление — это
main ← fix/unicode-username-lookups
closed 02:15AM - 14 Apr 26 UTC
Leverages Rails' built-in `normalizes` feature to handle username
normalization … consistently throughout the codebase. When you call
`User.where(username_lower: value)` or `find_by(username_lower: value)`,
ActiveRecord now automatically normalizes the input value.
Key changes:
- Adds `normalizes :username` (unicode normalize) and
`normalizes :username_lower` (unicode normalize + downcase) to User
- Adds `normalizes :email` (strip + downcase) to UserEmail
- Removes manual `.downcase` and `.map(&:downcase)` calls before AR queries
- Adds `User#matches_username?` method for comparing usernames
- Simplifies `filter_by_username` and `filter_by_username_or_email` scopes
to use `ILIKE ANY(ARRAY[?])` instead of branching on array vs single value
- Updates `filter_by_username` to normalize input for ILIKE patterns
- Updates `find_by_username` to rely on AR normalization
- Fixes a SQL injection vulnerability in search user ordering
- Uses before_save callback for username_lower assignment to ensure it
runs even when validation is skipped (e.g., finish installation flow)
- Adds shoulda matcher tests for username normalizations
The `normalize_username` class method is kept for cases where AR can't help:
raw SQL queries, ILIKE patterns, and direct comparisons.
Ref - https://meta.discourse.org/t/393646
но это слишком крупное изменение, чтобы я мог с комфортом принять его на данном этапе
Вместо этого я буду исправлять каждый «эндпоинт» по отдельности, чтобы упростить проверку и снизить риски.
Вот первый шаг
main ← fix-composer-mention-case-sensitivity
opened 08:30AM - 23 Apr 26 UTC
Mentioning `@SomeUser` in a topic the mentioned user can't see (restricted categ… ory, PM they aren't invited to, topic they've muted) silently skipped the "cannot see this mention" warning popup whenever the typed name contained any uppercase letter. Same for mixed-case group names. Mention validation itself worked because of an existing client-side `.toLowerCase()` workaround, so the bug was easy to miss — mentions stayed `<a class="mention">` but the user got no signal that the mentioned account wouldn't actually be notified.
Server side, `ComposerController#mentions` builds its `users` lookup keyed by `username_lower` and `groups` keyed by the case-preserved DB `name`, then iterated `@names.each { |n| users[n] || groups[n] }` without normalizing — so any uppercase character missed both hashes and `user_reasons`/`group_reasons` came back empty. Four downstream group helpers (`mentionable_group_ids`, `members_visible_group_ids`, `topic_allowed_group_ids`, `visible_group_ids_for_allowed_check`) used `where(name: @names)` which is case-sensitive in PostgreSQL, and the `SiteSetting.here_mention` membership test compared raw strings.
Client side, `link-mentions.js` cached `foundUsers` / `userReasons` / `foundGroups` / `groupReasons` by the case as typed, and the prosemirror `mention.js` warning lookup did `response.users.includes(name)` plus `response.user_reasons[name]` with the original case — both of which the server only ever returned in the casing it had on hand.
Normalize the controller's `@names` and `@allowed_names` once at the top of the action, switch all four group helpers to `LOWER(name) IN (?)`, lower-case the response keys, and lower-case client caches and lookups end to end. Also extract the inline notified-member query into `already_notified_member_count` and tighten the request specs to cover users, mentionable groups, group reasons in PMs, and `allowed_names` (both user and group branches) with mixed-case input.
https://meta.discourse.org/t/401292
7 лайков
Ethsim2
(Ethan )
13.Май.2026 15:03:53
5
После пересборки Discourse для 188 коммитов от 645cb014c0 до 102c93e2ea я заметил новую регрессию в редакторе Markdown.
Это всплывающее окно не имеет смысла, но оно появляется каждый раз, когда я пытаюсь вызвать своего кастомного агента @Forum_Research_Assis.
Мне удалось стабильно воспроизвести эту проблему, как показано в видео:
Полагаю, в этом же коммите отсутствует логика для пропуска ситуации, когда пользователь упоминает AI-агента.
Готов начать новый pull request, когда вы будете готовы, хотя у меня уже есть открытый PR на моём единственном аккаунте GitHub.
1 лайк
Похоже, мое «исправление» выявило эту проблему для AI-агентов
main ← fix-composer-mention-warning-ai-bots
opened 04:24PM - 13 May 26 UTC
Mentioning an AI bot (e.g. `@Forum_Research_Assis`) in a topic the bot's User re… cord can't see — like a category restricted to a group the bot isn't part of — surfaced the "this user cannot see this mention" warning popup in the composer. The warning is misleading: AI bots reply via `PostCreator.create!(... skip_guardian: true)` (`playground.rb`), so they respond regardless of whether their User can `Guardian#can_see?` the topic.
The previous case-insensitive fix (9a4cca29) exposed this latent behavior. Pre-fix, mixed-case names hit a case-sensitive hash miss in `ComposerController#mentions` and silently returned an empty `user_reasons`. Post-fix, the lookup hits correctly and the reachability check — which was always there — now fires for AI bot users that genuinely can't see the topic.
Adds a `:composer_mention_user_reason` plugin modifier, applied after the standard reason is computed in `user_reason`, so plugins can clear or transform it. The AI plugin registers against the modifier and returns `nil` for any user in `DiscourseAi::AiBot::EntryPoint.all_bot_ids` (covering both AI agent users and chat-bot-enabled LLM model users).
discobot and the system user are intentionally unaffected: discobot's `PostCreator.create!` does not skip the guardian, so the reachability warning remains accurate for it.
https://meta.discourse.org/t/401292
3 лайка