How would I go about tracking the unique page views for a page in a NodeJS app and saving them into the DB? Something like most app like Instagram or Dribbble etc. has where they count the views of a certain page uniquely means a page refresh won't recount.
What's the best algorithm behind this?
A simple approach would be to count the number of records in your "sessions" table/collection.
Another way would be to track all IPs that requests are made from, but this isn't advisable because you'll miss people behind a router.
If you just wish to track registered users, you could:
Maintain a 'lastLogin' property in the User model so you can make queries like "number of users who have visited since [datetime]"
Maintain a separate collection/table that maintains sessionIds, IPs, usernames and anything else you want. This would allow you to track very flexibly at the expense of more database work. This works for both registered and unregistered users since you track everything that identifies a visit.
You may also wish to reconsider if you want to track pageviews/sessions at all. If traction is all you want to measure, this will suffice. But if you wish to measure engagement, a better tactic would be to employ tracking at the action/controller level instead of session level. A combination of both is required to understand what users like and what they like not. Your purpose for tracking should decide what method/s you need to employ.
Use a widely-adopted solution: Google Analytics.
Good luck!
Related
I am building an ecommerce website which should be able to handle guest checkout. When a user visits the website, they are considered "Guests" unless they register / log-in to their account.
However, even as a guest, certain information needs to be stored about that visitor (partially incase they make an account in the furture, but also just for the website to function for them) like their prefered currency, email (if provided), cart and its contents, and an order_id (if they placed an order)
My question is which of the following choices would be better for handling this?
By the way: I am using NodeJS's express-session in this project.
Creating a "User" object for all new visitors and adding the user_id to the session. In this case that user object would need a feild called is_guest: true/false to tell the two apart, and it would also need a is_logged_in: true/false feild so the front-end can tell whether to load the log-in form or the profile page because a user object would always be present.
Only creating a "User" object after an account has been registered through the register form, and storing all data about the cart and email ect. for guests on the session object instead.
I can see problems with both. 1) could result in a really large database if all new visitors create a user object. 2) could result in information being scattered more and the session object becoming cluttered (especially if the cart becomes large). Having never done something like this before, I would appriciate any ideas about objections or solutions to the approaches and what you think would be the best.
Both solutions are fine, and I've seen both being used.
I would guess that storing things in the database is more common. Since you will probably be logging user interactions in your database anyways, it won't take up much more data. Secondly it's slightly simpler to use the same function to render pages for logged-in and logged-out users.
If you don't use a database, you may wish to use LocalStorage instead of a cookie since there are size limits to cookies (although few carts will get large enough to reach that limit).
In my use case, we have a number of clients who would like to access a (personalised) Kibana dashboard (pre-made in kibana). However, we wouldn't like different clients to see other clients data (for obvious reasons!)
The problem is, kibana "saves" dashboards as a URL (i.e.):
hxxp://myserver:8080/#/dashboard/Dash-1?embed&_g=(refreshInterval:(display:Off,pause:!f,section:0,value:0),time:(from:now-2y,mode:quick,to:now))&_a=(filters:!(),panels:!((col:1,id:UK-Log-Map,row:3,size_x:5,size_y:6,type:visualization),(col:1,id:Total-logs,row:1,size_x:12,size_y:2,type:visualization),(col:6,id:Logs-by-week,row:3,size_x:7,size_y:3,type:visualization),(col:6,id:Log-histogram,row:6,size_x:7,size_y:3,type:visualization)),query:(query_string:(analyze_wildcard:!t,query:'Name:Joe')),title:'Dash')
would represent a dashboard with 4 elements for "Joe" (filtered in the query - last part of URL).
Changing "joe" to any other client (i.e. "dave") would show their data, thus causing a security hole. What would be the best way to secure the data whilst providing the dashboards for each user?
I have full control over most of the tech used for this, so anything can be considered. I.e. libraries, proxies, RESTful services etc. This just needs a way forward!
Another user has tried to achieve this with encrypted URLs (js), but this seems a little hacky to me. There must be a cleaner way?
I was thinking of creating a voting app. The general idea is
browse a gallery
an awesome pic grabs your attention
hit the vote button underneath it
code magic happens
vote is counted
at a certain date, vote buttons become non-active and the app counts
the votes
This will be a web app, which means html5-css3-express.js-redis framework, or something similar.
How can I ensure that the user cannot vote for the same pic twice? By making him sign up? Huge procedure for just a voting app, dont you think? Plus, I guess I will also need a CAPTCHA thing to avoid unwanted, mass sign up.
But if I use coockies of HTML5 local Storage API, what is stopping the same user to clear his/her coockies and vote for the same pic again and again?
What is the best method?
Thanks alot
The most secure way is by using accounts to keep track of who has voted. Accounts are easy to implement in your application and you don't even need to hold the account data yourself if you use a service like Passport.js. You'll likely have a database set up already which makes it easy to keep account data as well.
The other method is to keep track of IP addresses but this has some issues (say, if a user uses a proxy). Also an IP address will cover all clients on a network means if one person votes on an image, all others will be unable to afterwards.
Easy way may be using npm package mongoose-voting where all logic for voting is already implemented.
There is also requirement for keeping track of users, so if you don't want a user to sign-up, you can automatically create a user by using the visitor’s IP address as the user’s ID.
There are many ways to manipulate vote results, but at the level you described, most of them are unnecessary.
well you dont need to build a login system these days as you can use any of the open id login authentication.E.g providers are facebook, google, yahoo and twitter.
I am in the process of designing document storage for CouchDB and would really appreciate some feedback. These documents are to represent "assets".
These databases will also be synced locally to the browser via pouchdb.
Requirements:
Each user can have many assets
Users can share assets with others by providing them with a URI such as (xyz.com/some_id). Once users click this URI, they are considered to have been "joined" and are now part of a group.
Group users can share assets of their own with other members of the group.
My design
Each user will have his/her own database to store assets - let's call it "user". Each user DB will be prefixed with the his/her unique ID.
Shared assets will be stored in a separate database - let's call it "group". shared assets are DUPLICATED here and have an additional field for userId (to indicate creator).
Group database is prefixed with a unique ID just like a user database is prefixed with one too.
The reason for storing group assets in a separate database is because when pouchdb runs locally, it only knows about the current user and his/her shared assets. It does not know about other users and will should not query these "other" users' databases.
Any input would be GREATLY appreciated.
Seems like a great design. Another alternative would be to just have one database per group ("role"), and then replicate from a user's group(s) into their local PouchDB.
That might get hairy, though, when it comes time to replicate back to the server, because you're going to have to filter the documents as they leave the user's local database, depending on which group-database they belong to. Still, you're going to have to do that on the server side anyway with your current design.
Either way is fine, honestly. The only downside of your current approach is that documents are duplicated on the server side (once per user-db and once per group-db). On the other hand, your client code becomes dead-simple, because you don't have to do any filtered replication. If you have enough space on your server not to worry about it, then I would definitely go with your approach. :)
Obviously some sort of mechanism for limiting login attempts is a security requisite. While I like the concept of an exponentially increasing time between attempts, what I'm not sure of storing the information. I'm also interested in alternative solutions, preferrably not including captchas.
I'm guessing a cookie wouldn't work due to blocking cookies or clearing them automatically, but would sessions work? Or does it have to be stored in a database? Being unaware of what methods can/are being used so I simply don't know what's practical.
Use some columns in your users table 'failed_login_attempts' and 'failed_login_time'. The first one increments per failed login, and resets on successful login. The second one allows you to compare the current time with the last failed time.
Your code can use this data in the db to determine how long it waits to lock out users, time between allowed logins etc
Assuming google has done the necessary usability testing (not an unfair assumption) and decided to use captchas , I'd suggest going along with them.
Increasing timeouts is frustrating when I'm a genuine user and have forgotten my password (with so many websites and their associated passwords that happens a lot , especially to me)
Storing attempts in the database is the best solution IMHO since it gives you the auditing records of the security breach attempts. Depending on your application this may or may not be a legal requirement.
By recording all bad attempts you can also gather higher level information, such as if the requests are coming from one IP address (i.e. someone / thing is attempting a brute force attack) so you can block the IP address. This can be VERY usefull information.
Once you have determined a threshold, why not force them to request the email to be sent to their email address (i.e. similar to 'I have forgotten my password'), or you can go for the CAPCHA approach.
Answers in this post prioritize database centered solutions because they provide a structure of records that make auditing and lockout logic convenient.
While the answers here address guessing attacks on individual users, a major concern with this approach is that it leaves the system open to Denial of Service attacks. Any and every request from the world should not trigger database work.
An alternative (or additional) layer of security should be implemented earlier in the req/ res cycle to protect the application and database from performing lock out operations that can be expensive and are unnecessary.
Express-Brute is an excellent example that utilizes Redis caching to filter out malicious requests while allowing honest ones.
You know which userid is being hit, keep a flag and when it reaches a threshold value simply stop accepting anything for that user. But that means you store an extra data value for every user.
I like the concept of an exponentially increasing time between attempts, [...]
Instead of using exponentially increasing time, you could actually have a randomized lag between successive attempts.
Maybe if you explain what technology you are using people here will be able to help with more specific examples.
Lock out Policy is all well and good but there is a balance.
One consideration is to think about the consruction of usernames - guessable? Can they be enumerated at all?
I was on an External App Pen Test for a dotcom with an Employee Portal that served Outlook Web Access /Intranet Services, certain Apps. It was easy to enumerate users (the Exec /Managament Team on the web site itself, and through the likes of Google, Facebook, LinkedIn etc). Once you got the format of the username logon (firstname then surname entered as a single string) I had the capability to shut 100's of users out due to their 3 strikes and out policy.
Store the information server-side. This would allow you to also defend against distributed attacks (coming from multiple machines).
You may like to say block the login for some time say for example, 10 minutes after 3 failure attempts for example. Exponentially increasing time sounds good to me. And yes, store the information at the server side session or database. Database is better. No cookies business as it is easy to manipulate by the user.
You may also want to map such attempts against the client IP adrress as it is quite possible that valid user might get a blocked message while someone else is trying to guess valid user's password with failure attempts.