아, 그렇군요. 로컬 디버깅을 조금 해보았는데, 기본 Discourse 설치 환경에서 100% 재현 가능하다는 것을 확인했습니다.
여기서 내용을 정리해 보겠습니다:
‘미분류(uncategorized)’ 관련 설정이 2가지 있습니다:
allow_uncategorized_topics 기본값 꺼짐(off)
suppress_uncategorized_badge 기본값 켜짐(on)
allow_uncategorized_topics가 비활성화된 경우(기본 설정)에도 이 카테고리의 존재가 특정 장소에서 노출(leak)되고 있습니다.
이를 우회하려고 미분류를 활성화하여 삭제하려 하면 다음과 같은 화면이 표시됩니다:
Discourse에서 이 카테고리는 매우 특이한 성격을 가지고 있습니다:
- 반드시 존재해야 합니다.
- 삭제할 수 없습니다.
- 수많은 로직과 장소에 주입(inject)되어 있습니다:
조건문(conditional)을 계속 추가함으로써 누출을 수정할 수는 있지만, 클라이언트와 서버 양쪽 모두에서 이미 적어도 10개나 쌓여 있을 것입니다.
아니면 근본적으로 이 문제를 해결할 수 있습니다. 관리자가 카테고리를 삭제할 수 있도록 허용하면, 해당 카테고리가 사라지므로 더 이상 이를 검사할 필요가 없게 됩니다.
제 제안은 다음과 같습니다.
- 두 설정과 숨겨진 설정
uncategorized_category_id를 모두 삭제합니다. - 기본 카테고리(default category)의 개념을 유지합니다(이미 존재하는 개념입니다) - 이미
default_composer_category가 있습니다. - '미분류(uncategorized)'는 더 이상 특별한 개념이 아니게 되므로, 고려해야 할 사항이 줄어듭니다.
- "배지 없는 카테고리"가 반드시 필요한 사람들을 위한 테마 컴포넌트를 제공합니다.
현재 검색 버그는 다음과 같은 방식으로 수정할 수 있습니다.
diff --git a/app/assets/javascripts/select-kit/addon/components/search-advanced-category-chooser.js b/app/assets/javascripts/select-kit/addon/components/search-advanced-category-chooser.js
index a678919d16..83a9ed27db 100644
--- a/app/assets/javascripts/select-kit/addon/components/search-advanced-category-chooser.js
+++ b/app/assets/javascripts/select-kit/addon/components/search-advanced-category-chooser.js
@@ -1,4 +1,5 @@
import { classNames } from "@ember-decorators/component";
+import { setting } from "discourse/lib/computed";
import CategoryChooserComponent from "select-kit/components/category-chooser";
import {
pluginApiIdentifiers,
@@ -7,11 +8,13 @@ import {
@classNames("search-advanced-category-chooser")
@selectKitOptions({
- allowUncategorized: true,
+ allowUncategorized: "allowUncategorized",
clearable: true,
none: "category.all",
displayCategoryDescription: false,
permissionType: null,
})
@pluginApiIdentifiers("search-advanced-category-chooser")
-export default class SearchAdvancedCategoryChooser extends CategoryChooserComponent {}
+export default class SearchAdvancedCategoryChooser extends CategoryChooserComponent {
+ @setting("allow_uncategorized_topics") allowUncategorized;
+}
import { render } from "@ember/test-helpers";
import { module, test } from "qunit";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import selectKit from "discourse/tests/helpers/select-kit-helper";
import SearchAdvancedCategoryChooser from "select-kit/components/search-advanced-category-chooser";
module(
"Integration | Component | select-kit/search-advanced-category-chooser",
function (hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function () {
this.set("subject", selectKit());
});
test("respects allow_uncategorized_topics setting when false", async function (assert) {
this.siteSettings.allow_uncategorized_topics = false;
await render(<template><SearchAdvancedCategoryChooser /></template>);
await this.subject.expand();
// Uncategorized category (ID 17 in test data) should not be present when setting is false
assert.false(
this.subject.rowByValue(17).exists(),
"uncategorized category is not available when allow_uncategorized_topics is false"
);
});
test("shows uncategorized category when allow_uncategorized_topics is true", async function (assert) {
this.siteSettings.allow_uncategorized_topics = true;
await render(<template><SearchAdvancedCategoryChooser /></template>);
await this.subject.expand();
// Uncategorized category (ID 17 in test data) should be present when setting is true
assert.true(
this.subject.rowByValue(17).exists(),
"uncategorized category is available when allow_uncategorized_topics is true"
);
});
test("has correct default options", async function (assert) {
await render(<template><SearchAdvancedCategoryChooser /></template>);
assert.strictEqual(
this.subject.header().label(),
"All categories",
"has correct default none label"
);
});
}
);
하지만 이는 고급 검색 버그만 해결하는 것이며, 우리는 여전히 구슬치기(wack-a-mole) 게임을 하고 있는 셈입니다…

