in the code I have tried to make the id of the user a global variable after creating and saving to mongodb so as to use the id in the posts route but seems not to work.Any help on this?
newuser.save().then(function(user){
if(user){
id=user._id;
req.session.user=user
req.flash("success","post added")
return res.redirect("/navashanti")
}}).catch((err)=>{
if(err){
console.log(err)}
` app.get("/posts",function(req,res){
user.findById().then(function(idresult){
if(idresult){
console.log(idresult)
res.render("home",{idresult:idresult})
}
}
`
you can define it with using GLOBAL or global.
global.id; // Declaration global variable - undefined
global.id= 1; //Global variable initialized to value 1.
var userID = global.id; // Using the global variable.
You CANNOT put data for one specific user into a global variable.
Even if you tried, it would be massively subject to timing and concurrency bugs. Your server can serve many users. If you put some data for userA into a global and then userB comes along, how does the server keep the right data with the right user. If you're just using a single global, it doesn't. It gets the data mixed up and one user gets the wrong data and another user's data is overwritten. It's a disaster. You cannot code servers this way.
Instead, data on a server has to be stored in a user-specific location so that each user's data is stored separately. Globals are shared by all users so they will not work for this. Some examples of a user-specific storage location are:
In a database record for that specific user
In a server-side session object that is uniquely for each specific user.
In a cookie which will be presented back to the server on future requests for that specific user.
If you want a specific coding suggestion for your specific issue, you'd have to show us an appropriate part of your code and describe exactly what problem you are trying to solve. The code you have in your question so far is incomplete, improperly formatted (so it's difficult to read) and you do not fully describe what problem you're actually trying to solve.
Adding on to the responses here, it's not a good idea to store the user id as a global variable. I'm not too familiar with the capabilities of MongoDB but I think you could try using sessions as that allows you securely preserve user data for the duration of a user session.
Related
I was looking around the internet to find out how I can send user status such as offline and online, etc to only friends using socket io. Some people were saying to use Redis. so I had a look and played around with it. I am also using mongodb to store friends and users.
This is my setup right now:
//Status List:
// 0 - offline
// 1 - online
// 2 - away
// 3 busy
//Set the status
redisClient.hmset ("online_status:userID", "status", "1");
//Check if someone is online
redisClient.hgetall ("online_status:userID", (err, reply) => {
console.log(reply)
})
Is it fine if I use it like this to get user status? or is there a better way to do this?
Another question is that, is that is it fine to keep looping hgetall or is there a better way to get multiple statuses at once?
You are using a hash type for storing a single information and you are using hgetall to retrieve it, so I assume you are not that familiar with redis data types yet. So first let me explain in short the three data types I'll talk about (find all types in the docs here https://redis.io/topics/data-types-intro ):
String: Is a simple key/value type, access it with set(key, value) and get(key, value)
Hash: Is a bunch of key/values stored under one redis key. Useful for storing attributes of an entity, like you could have a "userdata:userID" key and store name, avatar, status... with it. Access it with hset(key, field, value), hget(key, field), hgetall(key)
Set: Is a collection of unique strings, access it with sadd(key, member), sismember(key, member), smembers(key)
If you are only going to save the online status it would be cleaner to use a string type with set, get and del (since usually most users are offline most of the time, delete them and save space). For this simple key/value usecase redis is actually not even better than good old memcache.
If you intend to store more user related attributes (mood, motto, avatar...) you should rename it to "userdata:userID" and check with hget("userdata:userID", "status") and use hgetall only to retrieve all attributes.
Another approach could be to store all users in a SET: sadd('users:online', userID) and check with sismember('users:online', userID) or get all online users with smembers('users:online'). Suppose you store all friends in another SET friends:userID, you could grab all online friends of a user with a single intersect command sinter('friends:userID', 'users:online') - pretty nice and elegant IMHO, but this get's complicated with more different states and doesn't work with redis-cluster.
I would prefer the SET approach. Multiple hgets should also be fine until you encounter issues due to the one guy (there is allways one) that has thousands of contacts and refreshes all the time. At that point you could still introduce some friendship limits or caching.
In my app i have stores and products, in my store side i have a reference to products, my daubt now is how i set the route to delete a product for a store
should i do something like this router.delete('products/:id') this deletes a product since the store has a reference i just need to delete the reference, but my store has a id actually my store is my user, so i want to be sure that there is a user to be able to delete something i was imaginating something like this:
router.delete('stores/:id/products/:id'), but that feels kinda strange, what you guys think about this?
I believe your concern is that you have two parameters id in request string. Express supports specifying many parameters and you can name them whatever you like, they should be parsed and available to you as variables later (req.params.productId).
So you can do
router.delete('stores/:storeId/products/:productId')
Additional information you can find in express routing documentation.
I am looking at the documentation for Meteor and it gives a few examples. I'm a bit confused about two things: First, where do you build the db (keeping security in mind)? Do I keep it all in the server/private folder to restrict client-side access? And second, how do I define the structure? For example, the code they show:
Rooms = new Meteor.Collection("rooms");
Messages = new Meteor.Collection("messages");
Parties = new Meteor.Collection("parties");
Rooms.insert({name: "Conference Room A"});
var myRooms = Rooms.find({}).fetch();
Messages.insert({text: "Hello world", room: myRooms[0]._id});
Parties.insert({name: "Super Bowl Party"});
I don't understand how a collection's structure is defined. Are they just able to define a collection and throw arbitrary data into it?
To answer your first question about where to put the new Meteor.Collection statements, they should go in a .js file in a folder accessible by both client and server, such as /collections. (With some exceptions: any collections that are never synced to the client, like server logs, should be defined inside /server somewhere; and any local collections should be defined in client code.)
As for your second question about structure: MongoDB is a document database, which by definition has no structure. Per the docs:
A database holds a set of collections. A collection holds a set of
documents. A document is a set of key-value pairs. Documents have
dynamic schema. Dynamic schema means that documents in the same
collection do not need to have the same set of fields or structure,
and common fields in a collection’s documents may hold different types
of data.
You may also have heard this called NoSQL. Each document (record in SQL parlance) can have different fields. Hence, there's no place where you define initial structure for a collection; each document gets its "structure" defined when it's inserted or updated.
In practice, I like to create a block comment above each new Meteor.Collection statement explaining what I intend the structure to be for most or all documents in that collection, so I have something to refer to later on when I insert or update the collection's documents. But it's up to me in those insert or update functions to follow whatever structure I define for myself.
A good practice would probably be defining your collection on both client and server with a single bit of javascript code. In other words, put the following
MyCollection = new Meteor.Collection("rooms");
// ...
anywhere but neither in the client nor in the server directory. Note that this directive alone does not expose any sensitive data to nobody.
A brand new meteor project would contain by default the insecure and autopublish packages. The former will basically allow any client to alter your database in every possible way, i.e. insert, update and remove documents. The latter will make sure that all database content is published to everyone, no matter how ridiculously this may sound. But fear not! Their only goal is to simplify the development process at the very early stage. You should get rid of these to guys from your project as soon as you start considering security issues of any kind.
As soon as the insecure package is removed from your project you can control the database privileges by defining MyCollection.allow and MyCollection.deny rules. Please check the documentation for more details. The only thing I would like to mention here is that this code should probably be considered as a sensitive one, so I guess you should put it into your server directory.
Removing the autopublish package has effect on the set of data that will be sent to your clients. Again you can control it and define privilages of your choice by implementing a custom Meteor.publish routine. This is all documented here. Here, you have no option. The code can only run in the server environment, so the best choice would be to put it in the server directory.
About your second question. The whole buzz about NoSQL databases (like mongodb) is to put as few restrictions on the structure of your database as possible. In other words, how the collections are structured is only up to you. You don't have to define no models and you can change the structure of your documents (and or remove fields) any time you want. Doesn't it sound great? :)
I have a Mongoose model that holds Places. Each place has a lat/lng. I can define a Mongoose virtual attribute called distance that would be used to sort Places in ascending order. What's the best way to refer to the user's location information (let's assume it's stored in a session variable for now) from inside the distance virtual attribute?
For anything involving external data, adding a method to the schema would be a better choice than a virtual property.
I'm solving a similar issue. The problem is that methods are fine if you want perform an operation on a single value but I'm retrieving a list and want to inject a new virtual field into every record in the list - but use session data to generate the field. to do this safely (avoiding globals), I think I'll need to use a QueryStream and inject the new field using an ArrayFormatter that takes the session variables as constructor parameters.
This also looks like a job for LINQ so another approach might be to use one of the ports of LINQ to JS.
If you sill prefer to use virtuals, you can store user location info in NodeJs globals. For example this code may be set after user login:
global.user_location = user.location;
I am currently playing around with node.js and MongoDB using the node-mongo-native driver.
I tested a bit around using the Mongo console storing and retrieving JS objects. I figured out, that if I store an object that contains functions/methods the methods and functions will also be stored in the collection. This is interesting since I thought that functions could not be stored in MongoDB (with the exception of the system.js collection, as suggested by the Mongo docs).
Also it will not only store the methods but actually each method and member of the object's entire prototype chain. Besides that I dont like this behaviour and think it's unintuitive I mustn't have it.
I was going to manage users in a Mongo collection. To do this I have a User object containing all of the users methods functioning as a prototype for each instance of an user. The user object itself would only contain the users attributes.
If I store a user in the Mongo collection I only want to store the own properties of the user object. No prototype members and especially no prototype methods. Currently I do not see how to cleanly do this. The options that I figured might work are:
creating a shallow copy using foreach and hasOwnProperty and storing this copy in the collection.
Add a data attribute to each user that contains all the object's attributes and can be stored in the collection.
This just came to my mind writing this: I could also set all the prototypes properties to not enumerable which should prevent them from being stored in the collection.
However, I do have the same issues the other way around: when loading a user from a collection. AFAIK there is no way to change an objects prototype in JavaScript after it was created. And there's also no way to specify a prototype to use when Mongo instantiates objects it retrieved from a collection. So basically I always get objects that inherit from Object using Mongo. As far as I can tell I have 2 options to restore a usable user object from this point on:
Create a fresh object inheriting from User and copying each attribute on the result object to the newly created object. (Compatible to storing mechanisms 1 & 3)
Create a fresh object inheriting from User and storing the result object as a data attribute on the newly created object. (Compatible to storing mechanism 2)
Are my assumptions, especially about the possibility to specify a prototype for query results, correct? What's the right way to do it, and why? I'm surely not the first person struggling to store and resurrect objects in/from MongoDB using node.js.
Currently I would go with the approach 2/2. I don't really like it, but it is the most efficient and the only one that works cleanly with the API. However, I'd much rather hear that actually the API does nothing wrong, but I do for not knowing how to use it correctly. So please, enlighten me :)
I just recently realized, that it actually is possible to change an objects prototype in V8/node. While this is not in the standard it is possible in various browsers and especially in V8/node!
function User(username, email) {
this.username = username;
this.email = email;
}
User.prototype.sendMail = function (subject, text) {
mailer.send(this.email, subject, text);
};
var o = {username: 'LoadeFromMongoDB', email: 'nomail#nomail.no'};
o.__proto__ = User.prototype;
o.sendMail('Hello, MongoDB User!', 'You where loaded from MongoDB, but inherit from User nevertheless! Congratulations!');
This is used all over various modules and plugins - even core modules make use of this technique, allthough it is not ECMAScript standard. So I guess it is safe to use within node.js.
I'm not sure I'm following you question exactly... but fwiw one thing came to mind: Have you checked out the Mongoose ORM? (http://mongoosejs.com/)
It gives you a lot of options when it comes to defining models and methods. In particular "Virtuals" might be of interest (http://mongoosejs.com/docs/virtuals.html).
Anyway, hope it helps some!