Total vote count on topic list

Moved Developer FAQ

Suggested Topics

  • Threaded Discussions

    Moved Solved Developer FAQ
  • 0 Votes
    1 Posts

    If you have a custom theme that introduces custom user fields into the edit page, you might have noticed that the fields don't seem to show up on the frontend even if they're saved in the database.
    Likewise, if you have some custom data you want to maintain on a per-user basis, and you tried using user.updateProfile, you might've noticed that your fields don't seem to save.

    The reason for this behaviour is that the the user fields getter and setter are protected so that values in the user hash are not unintentionally overwritten, or that fields are retrieved that should not be.

    For example:

    nodebb-plugin-foobar saves a private user token in the user's hash. It is not meant to be retrieved. Another plugin calls user.getUsersFields() and that method naively returns everything in the user hash. The private key would then be considered leaked if it is accidentally exposed to the end user, even if unintentionally.

    Getter (retrieving user data)

    If you've saved a custom field into the user hash and you wish to retrieve it via User.getUsersFields(), you will have to explicitly whitelist it by attaching a hook listener to filter:user.whitelistFields. That plugin hook sends in { uids, whitelist }, where uids is an array of uids (requested by the calling script), and whitelist, which is an array containing user field properties.

    You can add a new entry to the whitelist thusly:


    { ... "hooks": [ { "hook": "filter:user.whitelistFields", "method": "addUserField" }, ] ... }


    library.addUserField = async ({ uids, whitelist }) => { whitelist.push('customField'); return { uids, whitelist }; };

    After doing so, a call to user.getUsersFields(uids, ['customField']); will have the customField property show up as it has been explicitly allowed.

    Setter (saving user data)

    Setting user data is comparatively simpler. We recommend using the user.updateProfile() method, as that has some sanity checks and special handling for certain fields. To allow the saving of a certain field, you will need to pass it in to the third argument of user.updateProfile():

    await User.updateProfile(callerUid, { uid, customField: 'value', }, ['customField']);
  • 0 Votes
    7 Posts

    @шЫкель-грубый said in How can I backdate topics and posts (for migration purposes)?:

    I'll also try to comment date changing in sources. I'm not familiar with JS but it looks obviously enough.

    Yes, this is probably the most direct solution. It'll get your script working with the correct timestamps, all you have to do is comment out that line in the file, and restart NodeBB.

  • 1 Votes
    1 Posts

    Your plugin may want to expose some user-specific options, and to accomplish that, you'll want to create a page accessible from within their user profile.

    In Harmony, plugin-added pages are added to the left-hand sidebar:

    In Persona, plugin-added pages are behind the overflow menu:

    You'll need to add listeners to two hooks, and modify your page template accordingly.


    Live example

    You'll need to specify a route in the user profile using this hook. In it, note the accountMiddlewares block, which contains some common middlewares that are sensible defaults. You'll need middleware.buildAccountData in order to retrieve some boilerplate data that all account routes need.


    Live example

    You'll then want to specify the menu option, including label, icon, and visibility options. visibility allows you to specify which users can see the option (e.g. self only, admins only, etc.)

    The template

    In your template for the user page, you'll want to prefix it with <!-- IMPORT partials/account/header.tpl --> and suffix it with <!-- IMPORT partials/account/footer.tpl -->. These two lines will wrap your template content with the theme-specific structure. For example, in Harmony, a sidebar is used in the accounts pages. The header and footer partials will ensure they are also present in your template. The middleware.buildAccountData middleware you added in the first step will ensure the data necessary is present.

  • 3 Votes
    1 Posts

    Let's say you have your own site and member database, with its own gated access to content, and you want to mimic this sort of arrangement with your forum.

    e.g. On member site, you have free users and paid users, and you want to only allow access to a couple super special categories on community site to paid users, while free users get the regular set of categories.

    The good news is, the Session Sharing plugin has had support for this since 2018!

    You'll want to enable the options in the session sharing plugin:


    You can opt to only add users to groups, only remove users from groups, or both. You can also specify which groups that the automatic group syncing applies to

    Once enabled, you need only update your shared cookie to contain a groups property, which is of type Array. This array contains the group names in NodeBB that the user should be a part of.

    If group leaving is enabled, then the user will be removed from any groups that are not in this array, upon login/revalidation.

    Once you have your group memberships sorted out, you'll want to restrict access to specific categories based on user group membership.

    You can do that from the ACP > Manage > Privileges page. Simply remove access for the registered-users groups from your choice of categories, and grant those viewing/posting privileges to the paid users group.