Проблема со страницей активации аккаунта после обновления до 3.4.0 (пустая страница)

Привет, команда Discourse,

Спасибо за такой замечательный продукт! Моё сообщество и я пользуемся им с удовольствием уже несколько лет. Недавно мы столкнулись с проблемой, и я был бы очень признателен за любую помощь.

После обновления с версии Discourse 3.3.0 до 3.4.0 новые пользователи видят пустую страницу (только заголовок и подвал) при нажатии на ссылку подтверждения по электронной почте для перехода на страницу «activate-account».


(тестовая ссылка будет предоставлена в конце этой статьи)

Предпринятые шаги:

  1. Проверка консоли разработчика: Ошибка указывает на то, что CSP блокирует внешние скрипты.

  2. Попытка изменения CSP через Cloudflare:


    Изменили политику и очистили кэш, но это не решило проблему.

  3. Попытка изменения CSP через панель администратора Discourse: Добавили ‘self’, ‘unsafe-eval’ и попытались использовать хеширование SHA256. Мы также ссылались на эту статью, но изменений не заметили.

  4. Сообщение об ошибке:


    Попробовали различные варианты ввода (например, ‘self’, ‘unsafe-eval’) и даже установили политику в режим «только отчёт». Всё равно безрезультатно.

  5. Очистка кэша: Изменений нет.

  6. Пересборка приложения: Пересобрали Discourse и очистили кэш, но проблема сохраняется.

Интересно, что эта проблема затрагивает не всех новых пользователей. Мы обнаружили, что с ней сталкиваются около 90% новых пользователей.

Будем очень благодарны за любые предложения или решения! Спасибо!

Вы пробовали безопасный режим?

@pfaffman
Только что попробовал и увидел следующее:

Есть ещё один сайт, где сообщается об ошибках CSP, связанных с конечной точкой /cdn-cgi/speculation: Refused to load the script 'site.com/cdn-cgi/speculation' because it violates the following Content Security Policy directive - #2 by simon. Мне неизвестно о подобных проблемах, которые могли быть зафиксированы ранее. Возможно, что-то изменилось либо в Cloudflare, либо в версии Discourse 3.4.0.

Конечная точка /cdn-cgi/speculation добавляется к доменам, зарегистрированным в Cloudflare, когда включена функция «Speed Brain». Speed Brain предназначена для ускорения производительности веб-сайта, позволяя Cloudflare предварительно загружать контент, когда пользователь наводит курсор на ссылку. Не уверен, что это совместимо с Discourse.

Я вижу, что при посещении https://community.lezismore.org/login в ответе возвращается заголовок Speculation-Rules. Это указывает на то, что функция Speed Brain включена. Согласно документации Cloudflare, похоже, что она включена по умолчанию.

Попробуйте отключить Speed Brain на вкладке Speed в панели управления Cloudflare. Инструкции по выполнению этой операции доступны здесь: Speed Brain · Cloudflare Speed docs.

В разделе «Caveats» (Ограничения) документации, на которую я ссылался, сказано:

  • Speed Brain не будет работать с ограничивающими конфигурациями Content Security Policy :up_right_arrow:, использующими атрибуты strict-dynamic или nonce-{hash}.

Если Speed Brain действительно совместима с Discourse, нам придётся выяснить, как добавить её в правила Content Security.

Спасибо за ваш ответ.

Я уже отключил настройку Speed Brain в Cloudflare и очистил кэш, как было рекомендовано, но, к сожалению, проблема сохраняется.

Вот ссылка на страницу активации нового тестового аккаунта сегодня, если кому интересно: https://community.lezismore.org/users/activate-account/34180b9eed9e1a1a1dbcca7eab66fb43

Вы можете войти на сайт? Если да, видите ли вы какие-либо сообщения об ошибках на странице журналов ошибок (https://community.lezismore.org/logs)?

Да, я могу войти на сайт.
Вот страница журнала:

Job exception: can't write unknown attribute

Детали следующие:

Сообщение (23685 копий)

Job exception: can't write unknown attribute

Backtrace

/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activemodel-7.1.4/lib/active_model/attribute.rb:236:in `with_value_from_database'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activemodel-7.1.4/lib/active_model/attribute_set.rb:60:in `write_from_user'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.1.4/lib/active_record/transactions.rb:435:in `restore_transaction_record_state'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.1.4/lib/active_record/transactions.rb:345:in `rolledback!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.1.4/lib/active_record/connection_adapters/abstract/transaction.rb:200:in `block in rollback_records'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.1.4/lib/active_record/connection_adapters/abstract/transaction.rb:263:in `run_action_on_records'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.1.4/lib/active_record/connection_adapters/abstract/transaction.rb:199:in `rollback_records'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.1.4/lib/active_record/connection_adapters/abstract/transaction.rb:527:in `block in rollback_transaction'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.1.4/lib/active_support/concurrency/null_lock.rb:9:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.1.4/lib/active_record/connection_adapters/abstract/transaction.rb:520:in `rollback_transaction'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.1.4/lib/active_record/connection_adapters/abstract/transaction.rb:539:in `rescue in block in within_new_transaction'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.1.4/lib/active_record/connection_adapters/abstract/transaction.rb:538:in `block in within_new_transaction'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.1.4/lib/active_support/concurrency/null_lock.rb:9:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.1.4/lib/active_record/connection_adapters/abstract/transaction.rb:532:in `within_new_transaction'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:344:in `transaction'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.1.4/lib/active_record/transactions.rb:361:in `with_transaction_returning_status'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.1.4/lib/active_record/persistence.rb:904:in `update!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/mini_scheduler-0.17.0/lib/mini_scheduler/manager.rb:156:in `process_queue'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/mini_scheduler-0.17.0/lib/mini_scheduler/manager.rb:77:in `worker_loop'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/mini_scheduler-0.17.0/lib/mini_scheduler/manager.rb:63:in `block (2 levels) in ensure_worker_threads'

Есть ещё несколько ошибок, в актуальности которых я не уверен, но всё же предоставляю их для справки, на всякий случай.

Сообщение

Исключение задачи: PG::SyntaxError: ERROR:  нулевая длина идентификатора в кавычках в или около """"
LINE 1: ...1506385, "success" = TRUE WHERE "scheduler_stats"."" IS NULL
                                                             ^



Обратная трассировка

/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/rack-mini-profiler-3.3.0/lib/patches/db/pg.rb:69:in `exec_params'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/rack-mini-profiler-3.3.0/lib/patches/db/pg.rb:69:in `exec_params'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/connection_adapters/postgresql_adapter.rb:768:in `block (2 levels) in exec_no_cache'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.8/lib/active_support/concurrency/share_lock.rb:187:in `yield_shares'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.8/lib/active_support/dependencies/interlock.rb:41:in `permit_concurrent_loads'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/connection_adapters/postgresql_adapter.rb:767:in `block in exec_no_cache'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.8/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.8/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.8/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.8/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/connection_adapters/abstract_adapter.rb:752:in `block in log'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.8/lib/active_support/notifications/instrumenter.rb:24:in `instrument'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/connection_adapters/abstract_adapter.rb:743:in `log'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/connection_adapters/postgresql_adapter.rb:766:in `exec_no_cache'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/connection_adapters/postgresql_adapter.rb:745:in `execute_and_clear'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/connection_adapters/postgresql/database_statements.rb:67:in `exec_delete'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/connection_adapters/abstract/database_statements.rb:175:in `update'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/connection_adapters/abstract/query_cache.rb:22:in `update'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/persistence.rb:513:in `_update_record'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/persistence.rb:1060:in `_update_row'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/locking/optimistic.rb:93:in `_update_row'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/persistence.rb:1082:in `_update_record'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/attribute_methods/dirty.rb:216:in `_update_record'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/callbacks.rb:463:in `block in _update_record'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.8/lib/active_support/callbacks.rb:99:in `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.8/lib/active_support/callbacks.rb:929:in `_run_update_callbacks'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/callbacks.rb:463:in `_update_record'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/timestamp.rb:121:in `_update_record'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/persistence.rb:1069:in `create_or_update'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/callbacks.rb:455:in `block in create_or_update'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.8/lib/active_support/callbacks.rb:99:in `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.8/lib/active_support/callbacks.rb:929:in `_run_save_callbacks'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/callbacks.rb:455:in `create_or_update'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/timestamp.rb:126:in `create_or_update'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/persistence.rb:648:in `save!'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/validations.rb:53:in `save!'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/transactions.rb:302:in `block in save!'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/transactions.rb:354:in `block in with_transaction_returning_status'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/connection_adapters/abstract/database_statements.rb:314:in `transaction'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/transactions.rb:350:in `with_transaction_returning_status'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/transactions.rb:302:in `save!'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/suppressor.rb:54:in `save!'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/persistence.rb:782:in `block in update!'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/transactions.rb:354:in `block in with_transaction_returning_status'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/connection_adapters/abstract/transaction.rb:319:in `block in within_new_transaction'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.8/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.8/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.8/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.8/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/connection_adapters/abstract/transaction.rb:317:in `within_new_transaction'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/connection_adapters/abstract/database_statements.rb:316:in `transaction'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/transactions.rb:350:in `with_transaction_returning_status'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8/lib/active_record/persistence.rb:780:in `update!'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/mini_scheduler-0.16.0/lib/mini_scheduler/manager.rb:134:in `process_queue'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/mini_scheduler-0.16.0/lib/mini_scheduler/manager.rb:70:in `worker_loop'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/mini_scheduler-0.16.0/lib/mini_scheduler/manager.rb:59:in `block (2 levels) in ensure_worker_threads'

Большое спасибо всем, кто готов помочь :folded_hands:

Судя по предоставленным вами деталям, мне не совсем понятно, где именно в коде Discourse возникает ошибка. Есть ли какая-либо информация на вкладках «info» или «env» на странице ошибки? Также в правом нижнем углу страницы есть кнопка «share», которая отображает все детали ошибки.

Я не уверен, что ошибка связана с этой проблемой, но кажется, что на вашем сайте что-то идёт не так с фоновыми задачами (sidekiq).

Полезная информация может также содержаться на странице /sidekiq вашего сайта. Как администратор, вы можете просмотреть её по адресу https://community.lezismore.org/sidekiq

Я проверил ваш сайт, и он на традиционном китайском языке. Возможно, вы столкнулись с той же проблемой, что и я: Wrong activate url

Похоже, мы столкнулись с одной и той же проблемой! После того как я обновил ссылку на страницу активации в шаблоне письма с:

%{base_url}/user/activate-account/%{email_token}

на:

%{base_url}/u/activate-account/%{email_token}

всё заработало как надо. Вероятно, проблема возникла из-за того, что шаблон письма не обновился автоматически из-за моих предыдущих кастомизаций, что помешало внесённым изменениям примениться после пересборки приложения.

Огромное спасибо @simon за невероятное терпение в помощи с отладкой и @th21 за предоставленную информацию!

Я продолжу отслеживать производительность приложения и сообщу об обновлениях, если возникнут какие-либо проблемы. Ещё раз спасибо вам всем!