Массив `groups` объекта JS пользователя не заполнен для нескольких пользователей

Я использую объект пользователя Discourse JS для проверки групп, в которые входит текущий пользователь.

У некоторых пользователей массив groups в JS-объекте пользователя возвращает корректный массив объектов, каждый из которых описывает группу, к которой принадлежит пользователь. Пример:

groups: Array (5)
0 {
  id: 1, 
  name: "admins", 
  has_messages: false
}
1 {
  id: 46, 
  name: "custom-group", 
  has_messages: false
}
2 {
  id: 3, 
  name: "staff", 
  has_messages: false
}
3 {
  id: 10, 
  name: "trust_level_0", 
  has_messages: false
}
4 {
  id: 11, 
  name: "trust_level_1", 
  has_messages: false
}

Однако у большинства пользователей массив groups просто пуст (0).
Я не могу понять, почему это происходит, поскольку эти пользователи действительно состоят в группах.
Я также проверил, связано ли это с «основной группой» (primary group), однако пользователи, у которых есть массив groups, также не состоят ни в какой основной группе, так что это не проблема.

Я использую соединение WP SSO для обработки входа пользователей, поэтому они входят в систему на экземпляре WP, а экземпляр Discourse по сути является «подчиненным» по отношению к WP: Discourse подтягивает все данные пользователей из WP, а вход обрабатывается в WP.
Я убедился, что «проблемный» пользователь хотя бы раз корректно вошел в систему в WP и хотя бы раз заходил в Discourse, чтобы быть авторизованным. Я могу подтвердить, что пользователь добавляется в нужные группы — просто это не отображается в массиве groups в JS-объекте пользователя.

Может ли кто-нибудь помочь понять, почему это происходит, и как это исправить?
Мне «отчаянно» нужно получить из этого массива группы, в которые входит пользователь :slight_smile:

Кстати, если это важно, вот как я получаю текущий JS-объект пользователя — до сих пор всё работало отлично, если не считать проблемы с группами, которая затрагивает некоторых пользователей (на самом деле, большинства).

$(document).ready(function() {
    $.ajax({
        type: 'GET',
        cache: false,
        url: 'https://discourse.domain.tld/session/current.json',
        dataType: 'json',
        xhrFields: {
            'withCredentials': true
        },
        success: function(result){
            var current_user_groups = result.current_user.groups;
            console.log(current_user_groups);// Это возвращает пустой массив для многих пользователей.
            console.log(result.current_user);// Все данные здесь корректно заполнены для ВСЕХ пользователей, кроме массива GROUPS.
        },
        error: function(result){
            console.log('Error: '+result);
        }
    });
});

Вы используете эндпоинт сессии для текущего авторизованного пользователя (то есть session/current). Только сотрудники получают «автоматические» группы (например, группы уровня доверия) через этот эндпоинт.

В качестве примера посмотрите https://meta.discourse.org/g. Это не тот же самый эндпоинт, но применяется тот же принцип. Вы увидите, что не можете увидеть все группы уровня доверия на Meta, потому что вы не сотрудник этого форума.

Чтобы получить все группы пользователя, включая автоматические, вам потребуется использовать авторизованный запрос, то есть с API-ключом. Если этот JavaScript выполняется на WordPress, вы можете использовать утилитарные функции WP Discourse для этого. Они выполнят запрос, используя API-ключ, который вы указали в интерфейсе администратора.

Правда? Я не думаю, что всё должно быть так сложно?


Это результат выполнения await $.ajax("/u/Lhc_fl.json")
Очевидно, я не сотрудник Meta, но я вижу свои «автоматические» группы.

@Lhc_fl, то есть вы получаете имя текущего пользователя (предположительно тем же AJAX, что и я?), затем делаете ещё один AJAX-запрос к JSON этого пользователя, а оттуда — к группе?

Мне также нравится подход @angus, хотя мой код находится на стороне Discourse… Я мог бы просто использовать тот же API-ключ и аутентифицироваться с его помощью?

Я предполагал, что поскольку я использую withCredentials, код выполняется только тогда, когда пользователь аутентифицирован, и что данные всегда будут одинаковыми.

Не совсем понимаю, почему данные не совпадают. Это вопрос безопасности — раскрывать, в какой группе состоит пользователь? Насколько я вижу, мы не передаём сами данные о группе или других её участниках.

В любом случае, сейчас приступаю к реализации предложенных подходов…

Спасибо!

Если вы разрабатываете компоненты для Discourse, думаю, самый простой способ — использовать API Discourse. Если же вы разрабатываете клиент, то, полагаю, имя пользователя должно было быть известно уже давно?

Для первого случая вот пример:

require("discourse/lib/plugin-api").withPluginApi("1.0.0", (api) => { console.log(api.currentUser()); });

Вы должны иметь возможность получить доступ к объекту текущего пользователя, и он покажет вам группы, о которых пользователь знает, что является их участником. Он уже загружен для каждого пользователя, поэтому вы будете обращаться к API плагина так же, как и к любой другой теме, которая работает с текущим пользователем. Примеры вы найдете в Кратком справочнике разработчика тем — просто просмотрите его.

В этой рекомендуемой теме есть пример: currentUser.groups doesn't match group_users table

Спасибо всем!

Хотя в данном конкретном случае groups всё ещё остаётся пустым (даже при использовании API пользователя вместо текущей сессии), мне удалось решить задачу, проверив ID группы в group_users, который также хранит те же данные, но без имени.

Я использовал свой первоначальный подход для получения данных, так как это всего лишь фрагмент, добавленный в Discourse как скрипт в head, без темы или плагина.

Мне не удалось заставить работать реальный api, но AJAX-подход работает так же хорошо для моих целей.

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