Proper way to update mongodb document from REST - node.js

simply I have AngularJs client. He wants to use every API using CRUD architecture. For example:
GET /user
GET /user/:id
POST /user
PUT /user/:id
DEL /user/:id
This is all endpoints he want to use for my schema.(using MongoDB database).
I have user schema like (simplified):
{
id : ObjectId("..."),
name: "Foo fooer",
itemIds : [
ObjectId("..."),
ObjectId("..."),
ObjectId("...")
]
}
and schema Items(do not need to show for questions).
We need to add/remove itemsId from user.itemIds.
Client wants to create new schema userItems:
{
id : ObjectId("..."),
userId : ObjectId("..."),
itemID : ObjectId("...")
}
and He want to remove user.itemIds from user schema and create 4 CRUD endpoints /userItems.
I think this wrong approach, normalizing the mongo database.
But I don't know which one of these is better from both sides(client and server).
1) Create 2 endpoints POST /UserItem, DEL /UserItem to update items in user.itemIds.
2) Update user.itemIds using existing API PUT /user, but client needs to send whole Array of itemsIds to update it(if there are many this is probably bad approach.
Client say these 2 approaches are bad, and he only know his SQL REST archictere(where everything is normalized). How can I prove him, that he is wrong? Because he said to me this:
Server to adapt to the client and not vice versa.
Thank you.

This is a good article about RESTful API.
In brief, your RESTful API should:
Focus on resource
Make sense
Consistence
For example:
When you want to add an item to an user: find the user first, not the other way around. So, POST users/:userId/items/ to add a new item to user is good. Or, DELETE users/:userId/items/:itemId to remove an item from the user.
When you want to find all the users who have this specific item: GET /items/:itemId/users/.

Related

What is the proper architecture for requesting a document vs. document details in a REST API?

I'm designing a REST API using NodeJS and Express for managing different types of documents (txt, pdf, doc, etc). The document model is something like:
{
id,
category,
name,
path,
tags,
etc..
}
I currently have a route to GET a single document.
/documents/:id
This route serves up the actual document. I would love some guidance on the proper way to serve up the document details (i.e. the name, category, etc). Should I use a different URL? Send details in headers? Use response.format? Make the client specify via query?
Edit: I should clarify that the documents will be stored on the server filesystem and will not be directly accessible by any client.
If the document details are coming from a different source, the most straightforward way is to set up a different endpoint, /document-details/:id.
Otherwise, if a document can be stringified into a JSON, you could nest both in the same response:
{
document: {},
details: {
category,
name,
path,
tags
}
}
I would recommend against sending any detail about document in the HTTP header, those are usually used to send the details about the response itself.

Permission for all users to post to a specific feed

I have been attempting to implement stream via react native and seem to be struggling with what looks like a permissions issue in relation to all users being unable to post to another 'entities' feed. My use case is essentially several 'topic' pages, where all users of my app can post to and comment etc. The topic page will also have an owner who can manage the page if needs be, so they too are essentially a 'user.
I've read elsewhere that global write permissions are not enabled by default so may need a member of the stream team to look at this for me if possible.
Here is the code I'm trying to use on the client side:
let user = client.feed('user', "bob");
let activity = {
actor: "bob",
verb: 'post',
object: "Hello world",
foreign_id: 'post:1',
to: ['user:topic-page-1'],
};
user
.addActivity(activity)
.then(data => {
console.log('success');
})
.catch(reason => {
alert(reason);
});
Another small issue I can't seem to get to the bottom of, is even when posting to the same user's timeline, the post username is always displaying as "Unknown" no matter what data I attach. What am I getting wrong here please?
For the actor field to be treated as a user entity, you should use a reference, something like client.currentUser or client.user('bob'). This should fix your post username issue.

Why the program mixes the code of all users connected when working with PostgreSQL local, ngrok and NodeJS?

I am in a serious problem with my code. I am developing a bot for Telegram using Node.JS and ExpressJS. To make requests I use ngrok and to store information PostgreSQL. My problem is: when running the program with only one user connected and talking to the bot and processing operations, the code runs very well. But, when multiple users are connected at the same time, the program mixes the code for all users. Example:
If the first user activates a boolean variable for specific selection or if the bot is processing an SQL query for this user and showing the result, the second and third user are affected ... Why?
I think that maybe PostgreSQL doesn't allow multiple transactions with the database running in the local machine or maybe its a problem with the code.
How can I solve this?
It sounds like you are using a variable server side. Since you have not provided code I will provide an example illustrating what I think the problem is.
Say you have a variable called basket which stores all the items in the users shopping basket. You update that variable when user A puts something in their basket but you update the same variable when user B puts something in their basket.
Instead you need to create a users object like this:
let users = {
"5": {
userid: 5,
basket: ['apple', 'banana']
},
"7": {
userid: 7,
basket: ['orange', 'apple']
}
}
When you make a request to the backend you pass the ID and the new item in the request (POST body typically) and get the correct user as follows:
let user = users[param.userid]
user.basket.push(item)
Then each user will be updated individually.

Using customer object information in private app

I'm currently trying to build a private app which will allow me to create a form which customers can use to update info like name, email address, etc.
I know that I can access this information in my template through the customer object:
https://help.shopify.com/themes/liquid/objects/customer
I also believe that I can send http requests through the admin api which would allow me to update a given customer object:
https://help.shopify.com/api/reference/customer#update
This is an example PUT request from that page
PUT /admin/customers/#{id}.json
{
"customer": {
"id": 207119551,
"email": "changed#email.address.com",
"note": "Customer is a great guy"
}
}
I think that in order to use this api (or at least use it securely) I need to use a private app. I found the following npm package which I would use to create the private app:
https://www.npmjs.com/package/shopify-node-api
This is an example of a PUT request from that page (I think this can be modified for customers):
var put_data = {
"product": {
"body_html": "<strong>Updated!</strong>"
}
}
Shopify.put('/admin/products/1234567.json', put_data, function(err, data, headers){
console.log(data);
});
Does anyone have any experience doing this as I'm unsure about a few things.
Will this PUT request be called when the url is loaded? So if I have an
<a> tag with href="/admin/products/1234567.json the request would load?
If so, this seems quite useless with the customer ID hardcoded in. Can I pass in the customer ID of whoever is logged in and clicking the link and use that as the last part of the request url somehow? In addition to this would it be possible to grab the form data that the user enters to use as the value for "email" or "note?
You should check out this answer shopify app proxy: send customer data or only customer ID for some pointers, discussion and links.
tl/dr; Don't rely on only the logged in customer id or you'll be opening yourself up to easy hackery.
So bascially you update the customer with the PUT you outlined in your question.
To get the id securely you:
Create a form with the customer id and make sure you have a server generated hash of that customer id to thwart bots (that's the reference post)
You post the customer data to a an app via a proxy url
You update the customer via a PUT to a constructed url.

Best approach to moderate posts in express nodejs mongodb

I am building a project in NodeJS, Mongodb, ExpressJS and at this time I would like to be able to moderate each post someone posts and therefore I am kindly asking what would best approach be to do so ?
I would have some users as Moderators and they would need to approve/moderate each post before the post is being released for public.
The same post could be seen only by the post creator during the time it's under review.
What would the best approach be to do something like this ?
Thnx in advance
Create post schema in mongoose
Keep a field in the schema, say
curated: {
type: Boolean,
default: false
}
This field would determine whether a post is curated and should be visible to the public, or not
Initially, curated = false
Create a front-end panel for the moderators to view the posts.
While querying in the MongoDB for the list of posts to be shown,
add appropriate filter, so that the post is visible only if the user is the creator of post or if his role is, let's say "moderator"
req.user is the current user.
Let's say req.user = {roles:["user", "moderator", "admin"]};
if(req.user.roles.indexOf("moderator")>-1){
db.getCollection("posts").find({user: req.user})
}
This will only return posts which have been created by the current user, or if the current user is a moderator
Now the user can choose to change post.curated to true, and update the post
Now, while fetching for the list of posts to be visible to public, add filter
db.getCollection("posts").find({curated:true})

Resources