Usually, a logged-in user gets all entries of a Content Type.
I created a "snippets" content type (_id,name,content,users<<->>snippets)
<<->>
means "has and belongs to many" relation.
I created some test users and make a request:
curl -H 'Authorization: Bearer eyJ...' http://localhost:1337/snippets/
Main Problem: an authenticated user should only see the entries assigned to him. Instead, a logged-in user gets all snippets, which is bad.
How is it possible to modify the fetchAll(ctx.query);
query to take that into account so it does something like fetchAll(ctx.state.user.id);
at the /
-route->find
-method ?
The basic find method is here:
find: async (ctx) => {
if (ctx.query._q) {
return strapi.services.snippet.search(ctx.query);
} else {
return strapi.services.snippet.fetchAll(ctx.query);
}
},
Sub-Question: Does strapi even know which user is logged in when I do Bearer-Token Authentication ?
That way, you should be able to retrieve the user info you need. Now, you can simply call the callback function with the username and email of your user. That way, Strapi will be able to retrieve your user from the database and log you in. Now, we need to configure our 'model' for our new provider.
Strapi applications are not meant to be connected to a pre-existing database, not created by a Strapi application, nor connected to a Strapi v3 database. The Strapi team will not support such attempts. Attempting to connect to an unsupported database may, and most likely will, result in lost data.
Default Strapi API is limiting to maximum 100 records only. We have a Content-Type with more than 100 records but since Strapi has default limit of 100, the API is only returning max 100 records.
Configure the new provider in the Provider.js file at the getProfile function. The getProfile takes three params: provider: The name of the used provider as a string. query: The query is the result of the provider callback. callback: The callback function who will continue the internal Strapi login logic.
You could set up a /snippets/me route under the snippets config.
That route could call the Snippets.me controller method which would check for the user then query snippets based on the user.
So in api/snippet/config/routes.json
there would be something like :
{
"method": "GET",
"path": "/snippets/me",
"handler": "Snippets.me",
"config": {
"policies": []
}
},
Then in the controller (api/snippet/controllers/Snippet.js
), you could do something like:
me: async (ctx) => {
const user = ctx.state.user;
if (!user) {
return ctx.badRequest(null, [{ messages: [{ id: 'No authorization header was found' }] }]);
}
const data = await strapi.services.snippet.fetch({user:user.id});
if(!data){
return ctx.notFound();
}
ctx.send(data);
},
Then you would give authenticated users permissions for the me route not for the overall snippets route.
A possibility would be to extend the query used by find
and findOne
in the controllers with a restriction regarding the logged in user. In this case you might also want to adapt the count
endpoint to be consistent.
This would result in:
withOwnerQuery: (ctx, ownerPath) => {
const user = ctx.state.user;
if (!user) {
ctx.badRequest(null, [
{ messages: [{ id: "No authorization header was found" }] },
]);
return null;
}
return { ...ctx.query, [ownerPath]: user.id };
};
find: async (ctx) => {
ctx.query = withOwnerQuery(ctx, "owner.id");
if (ctx.query._q) {
return strapi.services.snippet.search(ctx.query);
} else {
return strapi.services.snippet.fetchAll(ctx.query);
}
},
// analogous for for findOne
Depending on your usage of controllers and services you could achieve the same thing via adapting the service methods.
This kind of solution would work with the GraphQL plugin.
The above is correct, except with newer versions of strapi. Use find
and not fetch
:)
const data = await strapi.services.snippet.find({ user: user.id });
Strapi v3.0.0-beta.20
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With