Ben Irvin 801e3db415 add traverse query
fix single type

fix query

sanitize pagination count params

add comments

Cleanup the params/filters sanitize helpers

sanitize association resolver

Sanitize sort

fix graphql single type

fix graphql types

fix addFindQuery

Sanitize fields

Update sanitize sort to handle all the different formats

Update fields sanitize to handle regular strings & wildcard

Fix non scalar recursion

Add a traverse factory

Add visitor to remove dz & morph relations

Replace the old traverse utils (sort, filters) by one created using the traverse factory

add sanitize populate

await args

fix async and duplicate sanitization

sanitize u&p params

Add traverse fields

Fix traverse & sanitize fields

add traverse fields to nested populate

sanitize admin api filter queries

Co-authored-by: Jean-Sébastien Herbaux <Convly@users.noreply.github.com>

sanitize sort params in admin API

todo

make token fields unsearchable with _q

sanitize delete mutation

Update packages/core/admin/server/services/permission/permissions-manager/sanitize.js

Co-authored-by: Jamie Howard <48524071+jhoward1994@users.noreply.github.com>

fix errors on queries without ctx

rename findParams to sanitizedParams

Sanitize queries everywhere in the content manager admin controllers

sanitize single type update and delete

Ignore non attribute keys in the sanitize sort

Fix the sanitize query sort for nested string sort

Fix permission check for the admin

typo

sanitize upload

sanitize admin media library

sanitize admin users

Add missing await

Co-authored-by: Jean-Sébastien Herbaux <Convly@users.noreply.github.com>

set U&P users fields to searchable:false

add token support to createContentAPIRequest

add searchable:false to getstarted U&P schema

remove comment

sanitize component resolver

remove await

add searchable false to the file's folder path

Fix admin query when the permission query is set to null

add basic tests for filtering private params

add tests for fields

add pagination tests

Fix admin user fields not being sanitized

Fix convert query params for the morph fragment on undefined value

Traverse dynamic zone on nested populate

Handle nested sort, filters & fields in populate queries + handle populate fragment for morphTo relations

Sanitize 'on' subpopulate

Co-authored-by: Jean-Sébastien Herbaux <Convly@users.noreply.github.com>

don't throw error on invalid attributes

check models for snake case column name instead of assuming they are operators

Add first batch of api tests for params sanitize

Fix sort traversal: handle object arrays

Put back removePassword for fields,sort,filters

Add schemas and fixtures for sanitize api tests

Add tests for relations (sanitize api tests)

Move constant to domain scope

Rename sanitize params to sanitize query

Fix typo

Cleanup fixtures file

Fix variable name conflict

Update packages/core/admin/server/services/permission/permissions-manager/sanitize.js

Co-authored-by: Alexandre BODIN <alexandrebodin@users.noreply.github.com>

Update comment for array filters

Rename sanitize test

Test implicit & explicit array operator for filter

Remove unused code
2023-03-15 14:59:19 +01:00

210 lines
5.4 KiB
JavaScript

'use strict';
/**
* User.js controller
*
* @description: A set of functions called "actions" for managing `User`.
*/
const _ = require('lodash');
const utils = require('@strapi/utils');
const { getService } = require('../utils');
const { validateCreateUserBody, validateUpdateUserBody } = require('./validation/user');
const { sanitize } = utils;
const { ApplicationError, ValidationError, NotFoundError } = utils.errors;
const sanitizeOutput = async (user, ctx) => {
const schema = strapi.getModel('plugin::users-permissions.user');
const { auth } = ctx.state;
return sanitize.contentAPI.output(user, schema, { auth });
};
const sanitizeQuery = async (query, ctx) => {
const schema = strapi.getModel('plugin::users-permissions.user');
const { auth } = ctx.state;
return sanitize.contentAPI.query(query, schema, { auth });
};
module.exports = {
/**
* Create a/an user record.
* @return {Object}
*/
async create(ctx) {
const advanced = await strapi
.store({ type: 'plugin', name: 'users-permissions', key: 'advanced' })
.get();
await validateCreateUserBody(ctx.request.body);
const { email, username, role } = ctx.request.body;
const userWithSameUsername = await strapi
.query('plugin::users-permissions.user')
.findOne({ where: { username } });
if (userWithSameUsername) {
if (!email) throw new ApplicationError('Username already taken');
}
if (advanced.unique_email) {
const userWithSameEmail = await strapi
.query('plugin::users-permissions.user')
.findOne({ where: { email: email.toLowerCase() } });
if (userWithSameEmail) {
throw new ApplicationError('Email already taken');
}
}
const user = {
...ctx.request.body,
email: email.toLowerCase(),
provider: 'local',
};
if (!role) {
const defaultRole = await strapi
.query('plugin::users-permissions.role')
.findOne({ where: { type: advanced.default_role } });
user.role = defaultRole.id;
}
try {
const data = await getService('user').add(user);
const sanitizedData = await sanitizeOutput(data, ctx);
ctx.created(sanitizedData);
} catch (error) {
throw new ApplicationError(error.message);
}
},
/**
* Update a/an user record.
* @return {Object}
*/
async update(ctx) {
const advancedConfigs = await strapi
.store({ type: 'plugin', name: 'users-permissions', key: 'advanced' })
.get();
const { id } = ctx.params;
const { email, username, password } = ctx.request.body;
const user = await getService('user').fetch(id);
if (!user) {
throw new NotFoundError(`User not found`);
}
await validateUpdateUserBody(ctx.request.body);
if (user.provider === 'local' && _.has(ctx.request.body, 'password') && !password) {
throw new ValidationError('password.notNull');
}
if (_.has(ctx.request.body, 'username')) {
const userWithSameUsername = await strapi
.query('plugin::users-permissions.user')
.findOne({ where: { username } });
if (userWithSameUsername && _.toString(userWithSameUsername.id) !== _.toString(id)) {
throw new ApplicationError('Username already taken');
}
}
if (_.has(ctx.request.body, 'email') && advancedConfigs.unique_email) {
const userWithSameEmail = await strapi
.query('plugin::users-permissions.user')
.findOne({ where: { email: email.toLowerCase() } });
if (userWithSameEmail && _.toString(userWithSameEmail.id) !== _.toString(id)) {
throw new ApplicationError('Email already taken');
}
ctx.request.body.email = ctx.request.body.email.toLowerCase();
}
const updateData = {
...ctx.request.body,
};
const data = await getService('user').edit(user.id, updateData);
const sanitizedData = await sanitizeOutput(data, ctx);
ctx.send(sanitizedData);
},
/**
* Retrieve user records.
* @return {Object|Array}
*/
async find(ctx) {
const sanitizedQuery = await sanitizeQuery(ctx.query, ctx);
const users = await getService('user').fetchAll(sanitizedQuery);
ctx.body = await Promise.all(users.map((user) => sanitizeOutput(user, ctx)));
},
/**
* Retrieve a user record.
* @return {Object}
*/
async findOne(ctx) {
const { id } = ctx.params;
const sanitizedQuery = await sanitizeQuery(ctx.query, ctx);
let data = await getService('user').fetch(id, sanitizedQuery);
if (data) {
data = await sanitizeOutput(data, ctx);
}
ctx.body = data;
},
/**
* Retrieve user count.
* @return {Number}
*/
async count(ctx) {
const sanitizedQuery = await sanitizeQuery(ctx.query, ctx);
ctx.body = await getService('user').count(sanitizedQuery);
},
/**
* Destroy a/an user record.
* @return {Object}
*/
async destroy(ctx) {
const { id } = ctx.params;
const data = await getService('user').remove({ id });
const sanitizedUser = await sanitizeOutput(data, ctx);
ctx.send(sanitizedUser);
},
/**
* Retrieve authenticated user.
* @return {Object|Array}
*/
async me(ctx) {
const authUser = ctx.state.user;
const { query } = ctx;
if (!authUser) {
return ctx.unauthorized();
}
const sanitizedQuery = await sanitizeQuery(query, ctx);
const user = await getService('user').fetch(authUser.id, sanitizedQuery);
ctx.body = await sanitizeOutput(user, ctx);
},
};