2.8.0beta2 업데이트 이후 일부 사용자는 설정 등에 접근할 수 없음

이번 주早些에 2.7.0.beta2에서 2.8.0.beta2로 업데이트를 진행했습니다. 그 이후로 일반 계정(관리자 계정은 아닙니다)에서는 /u/ 페이지에 접근할 수 없게 되었습니다. 대신 404 오류가 발생합니다. 이 문제는 데스크톱(Firefox 84 및 89)과 모바일(Android에서 테스트)에서 모두 발생하며, 로그아웃, 캐시 삭제, 다시 로그인 후에도 동일하게 나타납니다.

이 문제가 다음 변경 사항과 관련이 있다고 추정됩니다:

저는 이 업데이트 훨씬 이전부터 discourse-user-card-badges 플러그인(버전 0.1으로 표시됨)을 설치해 왔습니다. 이 변경 사항과 아래에 있는 오류를 보면 플러그인이 변경 사항과 호환되지 않는 것 같습니다. 그렇다면 업데이트 시 플러그인을 비활성화하거나 비활성화를 요청해야 하지 않나요?

activemodel (6.1.3.2) lib/active_model/attribute_methods.rb:469:in `method_missing'
plugins/discourse-user-card-badges/plugin.rb:40:in `block (2 levels) in activate!'
(eval):93:in `_fast_attributes'
active_model_serializers (0.8.4) lib/active_model/serializer.rb:468:in `rescue in attributes'
active_model_serializers (0.8.4) lib/active_model/serializer.rb:455:in `attributes'
active_model_serializers (0.8.4) lib/active_model/serializer.rb:480:in `_serializable_hash'
active_model_serializers (0.8.4) lib/active_model/serializer.rb:359:in `serializable_hash'
active_model_serializers (0.8.4) lib/active_model/serializer.rb:343:in `as_json'
activesupport (6.1.3.2) lib/active_support/json/encoding.rb:22:in `encode'
activesupport (6.1.3.2) lib/active_support/json/encoding.rb:22:in `encode'
activesupport (6.1.3.2) lib/active_support/core_ext/object/json.rb:43:in `to_json'
active_model_serializers (0.8.4) lib/active_model/serializer.rb:331:in `to_json'
multi_json (1.15.0) lib/multi_json/adapters/oj.rb:56:in `dump'
multi_json (1.15.0) lib/multi_json/adapters/oj.rb:56:in `dump'
multi_json (1.15.0) lib/multi_json/adapter.rb:25:in `dump'
multi_json (1.15.0) lib/multi_json.rb:139:in `dump'
app/controllers/application_controller.rb:519:in `render_json_dump'
app/controllers/users_controller.rb:94:in `block (2 levels) in show'
actionpack (6.1.3.2) lib/action_controller/metal/mime_responds.rb:214:in `respond_to'
app/controllers/users_controller.rb:86:in `show'
actionpack (6.1.3.2) lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
actionpack (6.1.3.2) lib/abstract_controller/base.rb:228:in `process_action'
actionpack (6.1.3.2) lib/action_controller/metal/rendering.rb:30:in `process_action'
actionpack (6.1.3.2) lib/abstract_controller/callbacks.rb:42:in `block in process_action'
activesupport (6.1.3.2) lib/active_support/callbacks.rb:117:in `block in run_callbacks'
app/controllers/application_controller.rb:395:in `block in with_resolved_locale'
i18n (1.8.10) lib/i18n.rb:314:in `with_locale'
app/controllers/application_controller.rb:395:in `with_resolved_locale'
activesupport (6.1.3.2) lib/active_support/callbacks.rb:126:in `block in run_callbacks'
activesupport (6.1.3.2) lib/active_support/callbacks.rb:137:in `run_callbacks'
actionpack (6.1.3.2) lib/abstract_controller/callbacks.rb:41:in `process_action'
actionpack (6.1.3.2) lib/action_controller/metal/rescue.rb:22:in `process_action'
actionpack (6.1.3.2) lib/action_controller/metal/instrumentation.rb:34:in `block in process_action'
activesupport (6.1.3.2) lib/active_support/notifications.rb:203:in `block in instrument'
activesupport (6.1.3.2) lib/active_support/notifications/instrumenter.rb:24:in `instrument'
activesupport (6.1.3.2) lib/active_support/notifications.rb:203:in `instrument'
actionpack (6.1.3.2) lib/action_controller/metal/instrumentation.rb:33:in `process_action'
actionpack (6.1.3.2) lib/action_controller/metal/params_wrapper.rb:249:in `process_action'
activerecord (6.1.3.2) lib/active_record/railties/controller_runtime.rb:27:in `process_action'
actionpack (6.1.3.2) lib/abstract_controller/base.rb:165:in `process'
actionview (6.1.3.2) lib/action_view/rendering.rb:39:in `process'
rack-mini-profiler (2.3.2) lib/mini_profiler/profiling_methods.rb:85:in `block in profile_method'


actionpack (6.1.3.2) lib/action_controller/metal.rb:190:in `dispatch'
actionpack (6.1.3.2) lib/action_controller/metal.rb:254:in `dispatch'
actionpack (6.1.3.2) lib/action_dispatch/routing/route_set.rb:50:in `dispatch'
actionpack (6.1.3.2) lib/action_dispatch/routing/route_set.rb:33:in `serve'
actionpack (6.1.3.2) lib/action_dispatch/journey/router.rb:50:in `block in serve'
actionpack (6.1.3.2) lib/action_dispatch/journey/router.rb:32:in `each'
actionpack (6.1.3.2) lib/action_dispatch/journey/router.rb:32:in `serve'
actionpack (6.1.3.2) lib/action_dispatch/routing/route_set.rb:842:in `call'
lib/middleware/omniauth_bypass_middleware.rb:71:in `call'
rack (2.2.3) lib/rack/tempfile_reaper.rb:15:in `call'
rack (2.2.3) lib/rack/conditional_get.rb:27:in `call'
rack (2.2.3) lib/rack/head.rb:12:in `call'
actionpack (6.1.3.2) lib/action_dispatch/http/permissions_policy.rb:22:in `call'
lib/content_security_policy/middleware.rb:12:in `call'
lib/middleware/anonymous_cache.rb:355:in `call'
rack (2.2.3) lib/rack/session/abstract/id.rb:266:in `context'
rack (2.2.3) lib/rack/session/abstract/id.rb:260:in `call'
actionpack (6.1.3.2) lib/action_dispatch/middleware/cookies.rb:689:in `call'
actionpack (6.1.3.2) lib/action_dispatch/middleware/callbacks.rb:27:in `block in call'
activesupport (6.1.3.2) lib/active_support/callbacks.rb:98:in `run_callbacks'
actionpack (6.1.3.2) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
actionpack (6.1.3.2) lib/action_dispatch/middleware/actionable_exceptions.rb:18:in `call'
actionpack (6.1.3.2) lib/action_dispatch/middleware/debug_exceptions.rb:29:in `call'
actionpack (6.1.3.2) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
logster (2.9.6) lib/logster/middleware/reporter.rb:43:in `call'
railties (6.1.3.2) lib/rails/rack/logger.rb:37:in `call_app'
railties (6.1.3.2) lib/rails/rack/logger.rb:28:in `call'
config/initializers/100-quiet_logger.rb:23:in `call'
config/initializers/100-silence_logger.rb:31:in `call'
actionpack (6.1.3.2) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
actionpack (6.1.3.2) lib/action_dispatch/middleware/request_id.rb:26:in `call'
lib/middleware/enforce_hostname.rb:23:in `call'
rack (2.2.3) lib/rack/method_override.rb:24:in `call'
actionpack (6.1.3.2) lib/action_dispatch/middleware/executor.rb:14:in `call'
rack (2.2.3) lib/rack/sendfile.rb:110:in `call'
actionpack (6.1.3.2) lib/action_dispatch/middleware/host_authorization.rb:92:in `call'
rack-mini-profiler (2.3.2) lib/mini_profiler/profiler.rb:249:in `call'


message_bus (3.3.6) lib/message_bus/rack/middleware.rb:61:in `call'
lib/middleware/request_tracker.rb:177:in `call'
railties (6.1.3.2) lib/rails/engine.rb:539:in `call'
railties (6.1.3.2) lib/rails/railtie.rb:207:in `public_send'
railties (6.1.3.2) lib/rails/railtie.rb:207:in `method_missing'
rack (2.2.3) lib/rack/urlmap.rb:74:in `block in call'
rack (2.2.3) lib/rack/urlmap.rb:58:in `each'
rack (2.2.3) lib/rack/urlmap.rb:58:in `call'
unicorn (6.0.0) lib/unicorn/http_server.rb:634:in `process_client'
unicorn (6.0.0) lib/unicorn/http_server.rb:732:in `worker_loop'
unicorn (6.0.0) lib/unicorn/http_server.rb:547:in `spawn_missing_workers'
unicorn (6.0.0) lib/unicorn/http_server.rb:143:in `start'
unicorn (6.0.0) bin/unicorn:128:in `<top (required)>'
vendor/bundle/ruby/2.7.0/bin/unicorn:23:in `load'
vendor/bundle/ruby/2.7.0/bin/unicorn:23:in `<main>'

이것이 서드파티 플러그인인가요? 플러그인을 비활성화하는 방향으로 진행할 수 있을까요?

해당 플러그인은 공식 플러그인인 것으로 보입니다. 클릭하면 다음 주소로 이동합니다:

그리고 네, 플러그인을 비활성화하면 404 오류가 해결됩니다. 제 질문은 이것이 공식 플러그인이라고 생각하고 계속 작동할 것으로 예상했음에도 불구하고, 왜 수동으로 비활성화하는 단계가 필요한지입니다.

이 기능은 플러그인에서 코어로 이동한 기능인가요?

그렇다면 해당 플러그인에 비추천(deprecation) 안내를 추가해야 할 것 같습니다. @neil, 어떻게 생각하세요?

게시하기 전에 확인해 보니, 플러그인의 마지막 커밋이 2.8.0beta2 릴리스보다 최신이었습니다. 다시 살펴보니 해당 커밋이 “bot” 사용자에게서 온 것이므로 큰 의미를 가질 수 없을 것 같습니다.

더 자세히 살펴보니, 정확히 같은 기능은 아닌 것 같습니다. 배지는 사용자 카드의 왼쪽 하단 모서리에 큰 이미지로 표시되었습니다. 이 새로운 코어 기능은 사용자 카드 하단에 작은 배지 이미지와 배지 이름이 포함된 작은 박스를 제어하는 것 같습니다.

이 게시물 Why does eviltrout have a garbage man badge? 은 배지 기능의 초기 버전을 보여줍니다:

이 업데이트 이전에는 선택 범위가 획득한 업적과 관련된 이미지로 제한되어 있었습니다. 제 포럼의 모든 배지에 사용자 카드의 배지가 더 예뻐 보이도록 커스텀 이미지를 첨부해 두었습니다. (기본 이미지는, 음, “쓰레기” 수준입니다.)

아마도 UserBadges 테이블에 추가된 새로운 is_favorite 컬럼 때문인 것 같습니다.

SQL이 현재 깨져 있을 가능성이 높습니다.

UserBadge.attribute_names.map do |name|
              if name == 'is_favorite'
                "BOOL_OR(user_badges.#{name}) AS is_favorite"
              else
                "MAX(user_badges.#{name}) AS #{name}"
              end
            end

플러그인에 대한 수정 사항을 병합했습니다:

image 컬럼은 UX: Add image uploader widget for uploading badge images (#12377) · discourse/discourse@a23d0f9 · GitHub 커밋에서 Badge에서 제거되었는데, 당시 플러그인을 부분적으로 업데이트했지만 일부 위치를 놓쳤습니다.

코어 변경 사항이 플러그인을 깨뜨리지 않도록 최선을 다하고 있지만, 때로는 사용처를 놓치거나 플러그인의 테스트 커버리지가 부족할 수 있습니다(코어에 변경 사항이 있을 때마다 모든 공식 플러그인에 대해 테스트를 실행합니다). 위의 커밋에서 discourse-user-card-badges 플러그인에 더 많은 테스트를 추가하여 향후 유사한 문제를 방지했습니다.

실수가 일어날 수 있다는 점은 이해합니다. 제가 그 글을 썼을 때, 해당 플러그인의 기능이 새로운 코어 기능으로 대체되는 것으로 생각했습니다. 그 기능을 더 자세히 살펴본 후에야 두 가지가 서로 다른 것임을 깨달았습니다.