이 문제는 The road to stable, then permanent, for granular_anonymous_and_logged_in_groups_permissions 과 Granular group-based permissions for anonymous and logged in users 둘 다와 관련이 있습니다.
코어는 물론 많은 테마와 플러그인에서도 다음과 같은 패턴이 꽤 일반적입니다:
const groupIds = this.currentUser.groups.map((g) => g.id);
const allowedGroupIds = this.siteSettings.some_group_setting.split("|").map((groupId) => parseInt(groupId, 10));
const hasPermission = allowedGroups.some((groupId) =>
userGroupIds.includes(groupId)
);
if (!hasPermission) {
return;
}
그러나 이는 사용자 권한을 확인하는 효과적인 방법이 아닙니다. 사용자는 자신에게 표시되지 않는 그룹의 멤버가 될 수 있으며, 이러한 그룹은 클라이언트로 직렬화(serialization)되지 않아 보안 검사에 일관되고 정확하게 사용할 수 없습니다.
이 문제를 더 명확히 하기 위해 User 모델에서 currentUser.groups/user.groups를 currentUser.visibleGroups/user.visibleGroups로 이름 변경하고 기존 속성을 비추천(deprecated) 처리합니다. 이를 위한 초기 PR은 DEV: Deprecate calling user.groups on client directly - Pull Request #42711 - discourse/discourse - GitHub 입니다.
클라이언트에서 JavaScript를 사용하여 그룹 ID 목록에 기반한 사용자 권한을 확인해야 하는 경우 몇 가지 대안이 있습니다:
플러그인의 경우
current_user 직렬화기(serializer)에 새 속성을 추가하고, 서버 측에서 scope.in_any_groups?를 사용하여 사용자 권한을 확인하십시오. 이는 logged_in_users와 anonymous_users와 같은 의사 그룹(pseudogroups)도 포함합니다:
add_to_serializer(
:current_user,
:has_some_permission,
include_condition: -> do
SiteSetting.plugin_enabled
end,
) { scope.in_any_groups?(SiteSetting.group_list_setting_map) }
이후 클라이언트에서 this.currentUser.has_some_permission을 사용할 수 있습니다.
테마 및 컴포넌트의 경우
list_type: group을 가진 list 타입의 테마 설정에서 resolve_group_membership: true를 사용할 수 있습니다:
copy_button_allowed_groups:
default: "1|3"
type: list
list_type: group
resolve_group_membership: true
이 경우 클라이언트에서 settings.copy_button_allowed_groups는 settings.user_in_copy_button_allowed_groups(설정 앞에 user_in_ 접두사가 붙음)로 대체됩니다. 이는 사용자의 그룹 멤버십에 기반하여 서버 측에서 계산된 불리언 값입니다.
type: groups를 가진 객체 설정에도 동일하게 작동합니다. groups 속성에 resolve_group_membership: true를 추가하십시오:
menu_sections:
type: objects
default:
- name: section 1
groups:
- 1
- 3
schema:
name: menu section
properties:
name:
type: string
groups:
type: groups
resolve_group_membership: true
그런 다음 접근은 다음과 같습니다:
for (const section of settings.menu_sections) {
if (section.user_in_groups) {
// User is in at least one selected group for this section.
}
}