In the sample GraphQL query, if I change the ID, I can change the data of each user.
How can I restrict it to my account only?
mutation{ updateUser(input: { where:{ id:5 }, data: { age:54 } }){ user{ id age } } }
In the sample GraphQL query, if I change the ID, I can change the data of each user.
How can I restrict it to my account only?
mutation{ updateUser(input: { where:{ id:5 }, data: { age:54 } }){ user{ id age } } }
Answer also provided via the GitHub Discussion: https://github.com/strapi/strapi/discussions/8096
In this case, much like REST, you will want to use a policy. You can read more about policies and how to use them with GraphQL here:
https://strapi.io/documentation/v3.x/concepts/policies.html
https://strapi.io/documentation/v3.x/plugins/graphql.html#execute-a-policy-before-a-resolver
Unfortunately the link you provided with the solution is not available anymore.
There was no additional context in that discussion @larse it’s the exact same as I posted here.
@DMehaffy alright I followed the documentation and found a really nice tutorials as well.
The policy works very well for a post command. I have tried it in postman. Now I want that GraphQL use the policy as well. I read the following documentation GraphQL - Strapi Developer Documentation
Here is my code
// extensions/users-permissions/config/schema.graphql.js
module.exports = {
resolver: {
Mutation: {
updateUser: {
description: 'Update an existing user',
policies: ['plugins::users-permissions.userUpdate'],
},
},
},
};
The description is working but the policy just get ignored. (Strapi 3.5.2)
Also tried to change ‘plugins::users-permissions.userUpdate’ to ‘userUpdate’ but nothing happend.
What I do wrong?
Hello,
I think the problem is for graphql you must throw an exception not return ctx… :
To solve your problem (it work for me), modify your code as shown in this post : https://forum.strapi.io/t/correct-way-to-return-error-in-custom-service-through-graphql/1071/6
I hope this help you
Fabien
Hey @FabienCastell,
thank you so much! With the post I was able to see and bring the pieces together. It was needed that I write my own resolver. GraphQL doesn’t work with ctx. For everyone who look also for a solution to restrict user to only edit their own profiles here is the code:
app/extensions/users-permissions/config/schema.graphql.js
const Boom = require('boom')
const _ = require('lodash');
module.exports = {
resolver: {
Mutation: {
updateUser: {
description: 'Update an existing user',
policies: ['plugins::users-permissions.userUpdate'],
resolver: async (obj, options, { context }) => {
// If the user is an administrator we allow them to perform this action unrestricted
if (context.state.user.role.name === "admin") {
context.params = _.toPlainObject(options.input.where)
context.request.body = _.toPlainObject(options.input.data)
await strapi.plugins['users-permissions'].controllers.user.update(context)
return {
user: context.body.toJSON ? context.body.toJSON() : context.body,
}
}
// The data to mutate
const data = context.request.body;
// The Current User ID
const currentUserId = context.state.user.id
// The ID which the user like to mutate
const userToUpdate = context.params.id
// This limitate the user to only edit his own profile
if (currentUserId != userToUpdate) throw Boom.unauthorized('Unable to edit this user ID')
// Extract the fields to do some checks on it
const { firstname, lastname } = data;
// Check if firstname ist empty and if give badRequest
if (firstname && firstname.trim() === "" || firstname === "") throw Boom.badRequest("Firstname is required")
// Check if lastname ist empty and if give badRequest
if (lastname && lastname.trim() === "" || lastname === "") throw Boom.badRequest("Lastname name is required")
// Get the value of the where variable. In this case the user ID
context.params = _.toPlainObject(options.input.where)
// The Data to edit
context.request.body = _.toPlainObject(options.input.data)
// Edit the user data
await strapi.plugins['users-permissions'].controllers.user.update(context)
// Return the data
return {
user: context.body.toJSON ? context.body.toJSON() : context.body,
}
}
},
},
},
};
Create a custom endpoint for the user.
(60) Strapi API Custom Controller || Profile/me POST - YouTube
Thanks @larse for the example. This does work fine, but it seems that the policies are still. being ignored for graphql then? Is this a bug that needs reporting?
Is not it possible to use the current resolver to handle this?
@Ben_Gannaway exactly. This was what I was facing that the policies still be ignored or maybe GraphQL runs into an error because it can’t use “ctx”. For this I wrote the custom resolver. It’s a little bit more effort when you have to write two policies for REST and GraphQL with the same logic.
@LuisAlaguna Maybe there is an other way to use { context } for in the policies without writing a custom resolver for GraphQL. Unfortunately, I can’t find anything in the documentation about this.