Skip to content

sanitize.contentAPI not populating relations #14251

@sjoukedv

Description

@sjoukedv

Bug report

Required System information

  • Strapi version: 4.3.6
  • Database: Postgres

Describe the bug

I am trying to populate relations on the user object by calling api/users?populate=*. Using the custom extension below:

// path: src/extensions/users-permissions/strapi-server.js

const utils = require('@strapi/utils');
const { sanitize } = utils;

const getService = (name) => {
  return strapi.plugin('users-permissions').service(name);
};

export default (plugin) => {
    const sanitizeOutput = (user, ctx) => {
      // <-- here the user contains all the relations
      const schema = strapi.getModel('plugin::users-permissions.user');
      const { auth } = ctx.state;
    
      return sanitize.contentAPI.output(user, schema, { auth });
    };
  
    plugin.controllers.user.me = async (ctx) => {
      const authUser = ctx.state.user;
      const { query } = ctx;
  
      if (!authUser) {
        return ctx.unauthorized();
      }
  
      const user = await getService('user').fetch(authUser.id, query);
       
      ctx.body = await sanitizeOutput(user, ctx);
    };
  
    plugin.controllers.user.find = async (ctx) => {
      const users = await getService('user').fetchAll(ctx.query);
  
      ctx.body = await Promise.all(users.map((user) => sanitizeOutput(user, ctx)));
    };

    return plugin;
  };
schema
{
  collectionName: 'up_users',
  info: {
    name: 'user',
    description: '',
    singularName: 'user',
    pluralName: 'users',
    displayName: 'User'
  },
  options: { draftAndPublish: false, timestamps: true },
  attributes: {
    username: {
      type: 'string',
      minLength: 3,
      unique: true,
      configurable: false,
      required: false
    },
    email: {
      type: 'email',
      minLength: 6,
      unique: true,
      configurable: false,
      required: true
    },
    provider: { type: 'string', configurable: false },
    password: {
      type: 'password',
      minLength: 6,
      configurable: false,
      private: true
    },
    resetPasswordToken: { type: 'string', configurable: false, private: true },
    confirmationToken: { type: 'string', configurable: false, private: true },
    confirmed: { type: 'boolean', default: false, configurable: false },
    blocked: { type: 'boolean', default: false, configurable: false },
    role: {
      type: 'relation',
      relation: 'manyToOne',
      target: 'plugin::users-permissions.role',
      inversedBy: 'users',
      configurable: false
    },
    source: { type: 'enumeration', enum: [Array], required: true },
    subscriptions: {
      type: 'relation',
      relation: 'oneToMany',
      target: 'api::subscription.subscription',
      mappedBy: 'user'
    },
    favoriteSessions: {
      type: 'relation',
      relation: 'oneToMany',
      target: 'api::session.session'
    },
    uuid: { type: 'uid', required: false, minLength: 35 },
    newsletterOptIn: { type: 'boolean', default: false, required: false },
    firstName: { type: 'string' },
    lastName: { type: 'string' },
    createdAt: { type: 'datetime' },
    updatedAt: { type: 'datetime' },
    createdBy: {
      type: 'relation',
      relation: 'oneToOne',
      target: 'admin::user',
      configurable: false,
      writable: false,
      visible: false,
      useJoinTable: false,
      private: true
    },
    updatedBy: {
      type: 'relation',
      relation: 'oneToOne',
      target: 'admin::user',
      configurable: false,
      writable: false,
      visible: false,
      useJoinTable: false,
      private: true
    }
  },
  config: {
    attributes: {
      resetPasswordToken: [Object],
      confirmationToken: [Object],
      provider: [Object]
    }
  },
  kind: 'collectionType',
  __filename__: 'schema.json',
  __schema__: {
    collectionName: 'up_users',
    info: {
      name: 'user',
      description: '',
      singularName: 'user',
      pluralName: 'users',
      displayName: 'User'
    },
    options: { draftAndPublish: false, timestamps: true },
    attributes: {
      username: [Object],
      email: [Object],
      provider: [Object],
      password: [Object],
      resetPasswordToken: [Object],
      confirmationToken: [Object],
      confirmed: [Object],
      blocked: [Object],
      role: [Object],
      source: [Object],
      subscriptions: [Object],
      favoriteSessions: [Object],
      uuid: [Object],
      newsletterOptIn: [Object],
      firstName: [Object],
      lastName: [Object]
    },
    kind: 'collectionType'
  },
  modelType: 'contentType',
  modelName: 'user',
  connection: 'default',
  uid: 'plugin::users-permissions.user',
  plugin: 'users-permissions',
  globalId: 'UsersPermissionsUser',
  actions: undefined,
  lifecycles: undefined
}

Printing the user object before it is passed to sanitize.contentAPI.output(...) shows the object with the relations. After sanitizing the output only the favoriteSessions relation is populated and not the other relations like the default role.

Steps to reproduce the behavior

  1. Add a relation to the user object
  2. Add the extension in src/extensions/users-permissions/strapi-server.js (there is no overriding happening in the snippet above).
  3. Call the api/users/me endpoint

Expected behavior

I am expecting the sanitize function to return the relations on the user object as defined in the schema.

Additional context

There has been issues in the past regarding population see #11957.

Metadata

Metadata

Assignees

No one assigned

    Labels

    issue: bugIssue reporting a bugseverity: lowIf the issue only affects a very niche base of users and an easily implemented workaround can solvesource: plugin:users-permissionsSource is plugin/users-permissions packagestatus: can not reproduceNot enough information to reproduce

    Type

    No type

    Projects

    Status

    Archived

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions