خطأ في قاعدة بيانات Discourse عند إنشاء مستخدمين جدد عبر تسجيل الدخول الموحد SSO

ملخص

خطأ في قيد قاعدة بيانات Discourse ناتج عن قيم مفتاح مكررة يتم توليدها عندما يحاول مستخدمون ليس لديهم حساب تسجيل الدخول عبر SSO. يتسبب ذلك في ظهور خطأ داخلي في الخادم (500) عبر الوكيل الخارجي.

النقاش

في 28 أو 29 أغسطس، قمت بتحديث Discourse إلى أحدث إصدار تجريبي (v2.4.0.beta2) مع جميع الإضافات المثبتة. في نفس الوقت تقريبًا، قمت أيضًا بتحديث SeAT، وأعدت تكوين Discourse لاستخدام منفذ UNIX (UNIX socket)، والذي يمكن لـ Apache الخارجي أن يعمل كوكيل أو وكيل عكسي له. قبل ذلك، كان بإمكان الأشخاص تسجيل الدخول عبر SSO الخاص بـ EvE Online من خلال SeAT، وإذا لم يكن لديهم حساب بعد، فإن حسابات مستخدمين جديدة في Discourse كانت تُنشأ لهم تلقائيًا.

منذ ذلك الحين، لم يتم إنشاء أي حسابات مستخدمين جديدة بنجاح. وبدلاً من ذلك، قام الأشخاص الثلاثة الذين حاولوا تسجيل الدخول بتوليد أخطاء من نوع: فشل في إنشاء أو البحث عن المستخدم: ERROR: duplicate key value violates constraint "idx_category_users_user_id_category_id" DETAIL: Key (user_id, category_id)=(36, 6) already exists.. يكون category_id دائمًا 6، بينما يتغير user_id بين 33 و44، حتى مع تكرار الأرقام.

بافتراض أن category_id يشير إلى إدخالات في جدول categories، فإن القيمة 6 تبدو أنها تشير إلى فئة “Grass Clippings”. وبافتراض أن user_id يشير إلى إدخالات في جدول users، فإننا لا نملك أي إدخالات أعلى من 32.

الفئة “Grass Clippings” مقيدة للقراءة على الأقل بالنسبة للأشخاص المنتمين إلى المجموعات 2GTHRDiscourse، 2GTHRHighCouncil، وGRoLLake. وكان لدى شخص واحد على الأقل من الذين حاولوا الاتصال أمر add_groups يتضمن جميع هذه المجموعات الثلاث. لم يكن لدى الشخص الأول أيًا من هذه المجموعات الثلاث بعد، بينما كان لدى الشخص الأوسط واحدة على الأقل. جميعهم يولّدون نفس نوع خطأ قاعدة البيانات مع تفاصيل متطابقة باستثناء user_id.

الأشخاص الذين تم إنشاء حساباتهم في Discourse عبر تسجيل الدخول باستخدام SSO قبل الترقية لا يبدون وكأنهم يواجهون مشاكل في تسجيل الدخول.

الأشياء التي جربناها أو نظرنا فيها

  1. تعطيل خيار force https والعودة إلى استخدام وكيل Apache الخارجي للاتصال بمنافذ nginx.
    من غير المفاجئ أن هذا لم يكن له أي تأثير.

  2. تشخيص وإصلاح مشاكل SSO الشائعة

  3. احذر من الترميز المزدوج لعنوان URL لـ SSO payload

  4. تتبعنا المسار الخلفي (backtrace) ولاحظنا أن Discourse وصل إلى models/discourse_single_sign_on.rb في السطر 203 من دالة match_email_or_create_user() حيث يتم استدعاء User.create!(). للأسف، يتم تسجيل المعاملات (params) وما إلى ذلك بعد هذه النقطة، والتي لا يتم الوصول إليها أبدًا لأن العملية تتوقف وتُرجع خطأ HTTP 500. تحققت من shared/log/rails/production.log.* احتياطًا.

تعليقات أخرى

  • SeAT: بينما لم يتم تحديث إضافة SeAT لـ Discourse، تم تحديث العديد من مكونات SeAT. من الممكن أن يكون قد حدث تغيير في أحد هذه المكونات. ومع ذلك، فإن الخطأ واضح أنه من جانب Discourse عند محاولة إنشاء أو البحث عن مستخدم غير موجود، لذا أنا مشكك بعض الشيء في أن المشكلة من جانب SeAT.

  • Discourse: لا أتذكر الإصدار التجريبي من Discourse الذي كنت أستخدمه قبل الترقية. أعتقد أنه ربما مر شهر أو شهران على آخر ترقية قمت بها.

تفاصيل إضافية

Error
فشل في إنشاء أو البحث عن المستخدم: ERROR:  duplicate key value violates unique constraint "idx_category_users_user_id_category_id"
DETAIL:  Key (user_id, category_id)=(36, 6) already exists.
.    add_groups: CORPBLUEP,2GTHRAllianceMember,2GTHRALL,2GTHRHighCouncil,2GTHRCorpDirector,2GTHROfficer,DoWCitadelGunner,HCDIM,CORPDIRBLUEP,2GTHRCorpRecruiter,CORPDIRLAWNS,CORPDIR123HC,GRoLLake,DoWCapital,DoWFax,User,CORPHRBLUEP,2GTHRDiscourse
admin: 
moderator: 
avatar_force_update: 
avatar_url: http://image.eveonline.com/Character/740426190_128.jpg
bio: 
card_background_url: 
email: something@somewhere.com
external_id: 740426190
groups: 
locale: 
locale_force_update: 
name: Mindframe
nonce: e6f9da9e62b720a1efd97348ca20f101
profile_background_url: 
remove_groups: Superuser,SPRKYAllianceMember,DoWFieldMarshall,DoWScoutCoordinator,DoWFCGang,DoWFCAlliance,DoWFCSenior,DoWScout,DoWSuper,DoWTitan,DoWFC,2GTHRCorpCEO,DoWTitanBridging,DoLLogisticsSov,DoLLogisticsShipping,HCDoW,HCDoL,HCDoC,HCDoF,DoCDoIT,DoCTechnoMage,DoCDiplomat,DoCDepartmentLead,DoCRecruiterPilots,DoCRecruiterCorporations,DoCDiplomatLead,DoWBLOP,ViewGroups,CORPAIEU,CORPDIRAIEU,CORPZBMC,CORPC.R.Y,CORP123HC,CORPALTBH,CORPLAWNS,CORPDIRZBMC,CORPDIRC.R.Y,CORPDIRALTBH,CORPF3R4L,CORPDIRF3R4L,CORPSPRKY,CORPDIRSPRKY,CORPRMKR,CORPDIRRMKR,CORPHR123HC,CORPHRAIEU,CORPHRZBMC,CORPHRC.R.Y,CORPHRF3R4L,SPRKYDiscourse,CORPHRLAWNS,CORPDIROUSYN,CORPHROUSYN,CORPOUSYN,DoWReimbursementTeam,DoWCarrier,DoWDread,WCMember,WCALL,WCMindframesMarketVisitors
require_activation: 
return_sso_url: 
suppress_welcome_message: 
title: 
username: Mindframe
website:     /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.0.2/lib/patches/db/pg.rb:110:in `async_exec'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.0.2/lib/patches/db/pg.rb:110:in `async_exec'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/mini_sql-0.2.2/lib/mini_sql/postgres/connection.rb:118:in `run'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/mini_sql-0.2.2/lib/mini_sql/postgres/connection.rb:90:in `exec'
/var/www/discourse/app/models/user.rb:1403:in `set_default_categories_preferences'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:426:in `block in make_lambda'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:236:in `block in halting_and_conditional'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:517:in `block in invoke_after'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:517:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:517:in `invoke_after'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:133:in `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:816:in `_run_create_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/callbacks.rb:346:in `_create_record'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/timestamp.rb:102:in `_create_record'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/persistence.rb:705:in `create_or_update'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/callbacks.rb:342:in `block in create_or_update'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:132:in `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:816:in `_run_save_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/callbacks.rb:342:in `create_or_update'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/persistence.rb:308:in `save!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/validations.rb:52:in `save!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/transactions.rb:315:in `block in save!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/transactions.rb:387:in `block in with_transaction_returning_status'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/database_statements.rb:267:in `block in transaction'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/transaction.rb:239:in `block in within_new_transaction'
/usr/local/lib/ruby/2.6.0/monitor.rb:230:in `mon_synchronize'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/transaction.rb:236:in `within_new_transaction'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/database_statements.rb:267:in `transaction'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/transactions.rb:212:in `transaction'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/transactions.rb:385:in `with_transaction_returning_status'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/transactions.rb:315:in `save!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/suppressor.rb:48:in `save!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/persistence.rb:53:in `create!'
/var/www/discourse/app/models/discourse_single_sign_on.rb:203:in `block in match_email_or_create_user'
/var/www/discourse/lib/distributed_mutex.rb:31:in `block in synchronize'
/var/www/discourse/lib/distributed_mutex.rb:27:in `synchronize'
/var/www/discourse/lib/distributed_mutex.rb:27:in `synchronize'
/var/www/discourse/lib/distributed_mutex.rb:12:in `synchronize'
/var/www/discourse/app/models/discourse_single_sign_on.rb:186:in `match_email_or_create_user'
/var/www/discourse/app/models/discourse_single_sign_on.rb:74:in `lookup_or_create_user'
/var/www/discourse/app/controllers/session_controller.rb:169:in `sso_login'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/abstract_controller/base.rb:194:in `process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/rendering.rb:30:in `process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/abstract_controller/callbacks.rb:42:in `block in process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:132:in `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/abstract_controller/callbacks.rb:41:in `process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/rescue.rb:22:in `process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/instrumentation.rb:34:in `block in process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/notifications.rb:168:in `block in instrument'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/notifications/instrumenter.rb:23:in `instrument'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/notifications.rb:168:in `instrument'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/instrumentation.rb:32:in `process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/params_wrapper.rb:256:in `process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/railties/controller_runtime.rb:24:in `process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/abstract_controller/base.rb:134:in `process'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionview-5.2.3/lib/action_view/rendering.rb:32:in `process'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.0.2/lib/mini_profiler/profiling_methods.rb:78:in `block in profile_method'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal.rb:191:in `dispatch'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal.rb:252:in `dispatch'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/routing/route_set.rb:52:in `dispatch'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/routing/route_set.rb:34:in `serve'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/journey/router.rb:52:in `block in serve'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/journey/router.rb:35:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/journey/router.rb:35:in `serve'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/routing/route_set.rb:840:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-protection-2.0.7/lib/rack/protection/frame_options.rb:31:in `call'
/var/www/discourse/lib/middleware/omniauth_bypass_middleware.rb:68:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/tempfile_reaper.rb:15:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/conditional_get.rb:25:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/head.rb:12:in `call'
/var/www/discourse/lib/content_security_policy/middleware.rb:12:in `call'
/var/www/discourse/lib/middleware/anonymous_cache.rb:219:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/session/abstract/id.rb:232:in `context'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/session/abstract/id.rb:226:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/cookies.rb:670:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:98:in `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/callbacks.rb:26:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/debug_exceptions.rb:61:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/logster-2.3.2/lib/logster/middleware/reporter.rb:43:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:38:in `call_app'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:28:in `call'
/var/www/discourse/config/initializers/100-quiet_logger.rb:18:in `call'
/var/www/discourse/config/initializers/100-silence_logger.rb:31:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/request_id.rb:27:in `call'
/var/www/discourse/lib/middleware/enforce_hostname.rb:17:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/method_override.rb:22:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/executor.rb:14:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/sendfile.rb:111:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.0.2/lib/mini_profiler/profiler.rb:171:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/message_bus-2.2.2/lib/message_bus/rack/middleware.rb:57:in `call'
/var/www/discourse/lib/middleware/request_tracker.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/engine.rb:524:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/railtie.rb:190:in `public_send'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/railtie.rb:190:in `method_missing'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/urlmap.rb:68:in `block in call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/urlmap.rb:53:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/urlmap.rb:53:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:605:in `process_client'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:700:in `worker_loop'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:548:in `spawn_missing_workers'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:144:in `start'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/bin/unicorn:128:in `<top (required)>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/bin/unicorn:23:in `load'
/var/www/discourse/vendor/bundle/ruby/2.6.0/bin/unicorn:23:in `<main>'
3 إعجابات

هذا يتعلق بهذا الكود:

ما حدث هنا هو أننا عدّلنا الفهرس على category_user على النحو التالي:

هل لديك مجموعة تكون كلاهما: مُشاهدة افتراضياً وتتبع افتراضياً في إعدادات الموقع؟

انظر إلى: default categories watching و default categories tracking و default categories muted و default categories watching first post.

هذا الإصلاح يُحل المشكلة:

diff --git a/app/models/user.rb b/app/models/user.rb
index c1a94949a6..85b2ca9244 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1390,10 +1390,15 @@ class User < ActiveRecord::Base
     return if self.staged?
 
     values = []
+    # allocate set later
+    seen = nil
 
     %w{watching watching_first_post tracking muted}.each do |s|
       category_ids = SiteSetting.get("default_categories_#{s}").split("|").map(&:to_i)
       category_ids.each do |category_id|
+        seen ||= Set.new
+        next if seen.include?(category_id)
+        seen << category_id
         next if category_id == 0
         values << "(#{self.id}, #{category_id}, #{CategoryUser.notification_levels[s.to_sym]})"
       end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index cc50d88b2e..4075ee6194 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1603,8 +1603,12 @@ describe User do
 
       SiteSetting.default_categories_watching = category0.id.to_s
       SiteSetting.default_categories_tracking = category1.id.to_s
-      SiteSetting.default_categories_muted = category2.id.to_s
+
+      # this is invalid, but we don't validate so ensure nothing breaks
+      SiteSetting.default_categories_muted = "#{category2.id}|#{category0.id}"
+
       SiteSetting.default_categories_watching_first_post = category3.id.to_s
+
     end
 
     it "has overriden preferences" do

لكنني لست معجباً بهذا الإصلاح؛ يجب أن تتحقق إعدادات الموقع من عدم وجود تداخل عند الحفظ، ويجب علينا نقل البيانات السيئة بعيداً.

@Daniel أعتقد أنك أدخلت القيد الجديد هنا، ربما يمكنك المتابعة بإضافة تحقق عند قيام المستخدمين بتعيين إعدادات الموقع؟

3 إعجابات

لديني فئات متتبعة وفئات مُشاهدة، لكن لا يوجد تداخل بينها. جميعها فئات من المستوى الأعلى. ومع ذلك، لدي تداخل بين “الفئات الافتراضية للمراقبة” و"الفئات الافتراضية لمراقبة أول منشور". توجد فئة واحدة في كلا القسمين، وهذه الفئة تتطابق مع معرف الفئة المذكور في خطأ قيد قاعدة البيانات الخاصة بي. هل يمكن أن يكون ذلك جزءًا من المشكلة؟

ردًا على نفسي: إزالة التصنيف من default categories watching first post بحيث يكون موجودًا فقط في default categories watching حل المشكلة؛ الآن يمكن للمستخدم بدون حساب الذي لم يكن بإمكانه تسجيل الدخول سابقًا القيام بذلك.

3 إعجابات

لقد واجهتُ هذا الخطأ للتو.

لم يتمكن المستخدمون من تسجيل الدخول لأن ملاحظات التوظيف وملاحظات الشريك تكرر ظهورهما في default categories regular.

إعجاب واحد (1)

يجب أن يكون من السهل جدًا منع التكرار عند حفظ الإعداد. غير متأكد من إصلاح السجل، مع ذلك.

@vinothkannans هل يمكنك التأكد من أن هذه الإعدادات الافتراضية تُنظف الأمور عند الحفظ؟

  • إزالة التكرارات
  • إذا كنت تحفظ “المشاهدة الافتراضية” للفئة A … وكان “التتبع الافتراضي” مضبوطًا بالفعل لـ A، فأظهر خطأً يوضح المشكلة
إعجاب واحد (1)

أقوى تخميني لكيفية حدوث ذلك هو:

  1. إنشاء “ملاحظات الشركاء” كفئة مستقلة وجعلها “الفئات الافتراضية العادية”.
  2. إنشاء “ملاحظات التوظيف” كفئة مستقلة وجعلها “الفئات الافتراضية العادية”.
  3. إنشاء “المنظمين” كفئة مستقلة وجعلها “الفئات الافتراضية العادية”.
  4. تغيير إعدادات “ملاحظات الشركاء” و"ملاحظات التوظيف" لجعل الفئة الأصلية لهما هي “المنظمين”، وأعتقد أنني لم أقم بإجراء أي تغييرات على إعداد “الفئات الافتراضية العادية”.

أدعم بالتأكيد إصلاح هذا الخطأ لأن عدم قدرة المستخدمين الجدد على التسجيل يعني كارثة + صعوبة في اكتشافها، حيث من المرجح أن يستسلم المستخدمون الجدد ولا يتواصلون مع أي شخص للمساعدة.

في الوقت الراهن، ربما يمكن تضمين رسالة الخطأ عبارة: “إذا استمرت مشاكلك في التسجيل، يرجى التواصل مع البريد الإلكتروني للموقع للحصول على الدعم؟”

إعجاب واحد (1)