I'm managing a multiuser app using Ionic 3.x, PouchDB, CouchDB and a node.js server running Superlogin. The app is steadily growing and I want to introduce a new feature.
My app has normal users and superusers. Each normal and superuser in my application gets it's own user database. There is also a shared database, let's call it the generaldb.
And here's my problem: Both users can create documents. These documents are synced to the userdb as well as to the general db. These documents have, amongst other things, a keyword (e.g. "colour": "green"). Superusers have access to a specific key. (In the above example that would mean that there are for example 5 superusers who can access the key green.)
Now, no normal user should be able to read, update or write other user's documents on the generaldb. Superusers should be able to read, update or write documents in the generaldb depending on which key they have access to. But they should not be allowed to change documents that don't match their key.
How can I restrict access for normal users in the generaldb, so that only documents created by themselves are synced to their devices and so that they couldn't change other users documents?
How can I ensure, superusers can change normal users documents, as long as they have access to the correct key?
How can I ensure superusers cannot change their own key, so that when number 2 is accomplished, they cannot manually work around the system?
One of the ideas of mine is to only let the users access their own db and have the shared db only accessible by superusers and then do a filtered replication of the userdb to the shared db. But this only solves 1 and seems very inefficient.
Related
Hi I working on a simple application using Azure CosmosDB. Now I want to use resource tokens to provide specific access to documents and collection in the DB. In the permission modes there are PermissionMode.Read and PermisssionMode.All. So I am assuming that PermissionMode.All allows the users to read, write, delete and post. If what I am assuming is correct, I specifically do not want my users to delete or post in a certain collection. How do I achieve this?
For better understanding, my database contains a container called users, which contains user information along with their posts and likes per post and stuff. Now I allow all my users to read (view posts of other users) and write (give a like or increment the like field), but I want to allow Post and Delete to a document to only the user of the document.
The finest granularity for assigning permissions is a partition key value so the only way to grant per document permissions is if your document id is also the partition key. If your partition key is userId and the user profile and posts, etc. all share that same partition key then that should work for you. Here is a sample that creates a permission on a partition key for a user.
I'm developing an application with NodeJS, ExpressJS and MongoDB. Currently I'm working on the user registration process. I would like to store the user account temporary until the user has verified his email address, if the email address is not verified within a certain amount of time, I would like to remove the temporary account.
Currently I've following two ideas to solve the issue:
Creating a mongoose TempUserModel (besides the UserModel), i.e. if the user does the registration a temp user will be created, as soon as the user verified his email address, the temporary user account will be copied to the real Users collection. Some cronjobs could be setup to delete not verified user accounts after a certain amount of time (probably there are better solutions to let expire a mongodb record)
Setup redis to store the temporary user account data, as soon as the email address get verified, a new user will be created in mongodb. With this solution an expire date could be set to remove not verified accounts after a certain amount of time)
Is it better to store a temporary user account in Redis or in MongoDB?
I would recommend storing the temporary user accounts in MongoDB. Storing them in MongoDB has three advantages over Redis:
If you store a temporary user in MongoDB, it will be very easy to convert them to a real user once they have verified. In fact, you could even have the temporary users and verified users share the same schema, with a has_verified field in that schema being the only difference between the two kinds of users. Changing has_verified to true is a lot easier than saving data from Redis to Mongo.
If you are not already planning to create a Redis database for your project, you will only have to maintain MongoDB. Maintaining MongoDB requires less effort and fewer computation resources than maintaining both Redis and MongoDB.
If you ever make changes to your user schema in the future, it would be easier to only make those changes in once place, i.e. MongoDB, rather than to make those changes in two places.
I'm new to couchDB and still reading tutorials. My question is if it is the normal way to represent every user of my application as a new database user, as it seems to be explained that way everywhere I look?
Let's say I have an online game with many different players - would I create a new "database user" for every player who registers? Or would I make my own database "players" and create a sign-in logic in the app? Not being used to document-driven DB's it seems strange to me not to distinguish between db-users and users of my application...
You could do it either way. First about couchdb users
Users in couchdb are stored in a special _users database
Database permissions are handled by a special _security document. This is specific to every database.
In security documents you add users that you have already stored in the _users database previously.
So you can certainly create a database per user. Before doing that ask yourself if the data that you store in each database is truly independent. Because you can't run map reduce queries across databases. So if you are planning to do aggregation across data for different users then this approach will not work.
Couchdb can also help you with app level authentication. Since couchdb uses a cookie based authentication:
Store your "business logic users" in the special _users database.
Authenticate it with the _session endpoint.
Extract the cookie header and sent it with your application headers.
All the logic for authentication is implemented for you by couchdb. All you have got to do is manipulate headers. Send the cookie from your application and when authenticating with couchdb send it with couchdb's headers.
If you prefer to write entire session management in your application that is fine too. In this case simply store the users in your database and verify that they exist before authenticating them. Like you would do with another database.
The benefit of using couchdb is that it is secure by default --using pbkdf2 encryption scheme to encrypt passwords.
If you instead want to manage all docs using a single database, but still implementing read/write ACLs, you can check the Chatty Couchapp Tutorial app from Smileupps App Store
It's a pure couchapp, relying on CouchDB only as its backend. The tutorial is still work in progress but the couchapp is fully working and you can download its source code.
It implements role/user based read/write ACLs using a single CouchDB database. This way you don't have to setup N replications where N depends on the number of your users. You only have one database containing all your data, easy to be queried on the fly(with temporary views) and for maintenance operations. Of course you can decide to increase the number of database, depending on type of your data and use cases.
A single couchapp contains all the necessary code for frontend, admin dashboard and server side API implementing business rules
The user, depending on his roles have different access to different sections. i.e. he can access the frontend website, but not the admin dashboard.
You can install the free trial, then download the source code with Smileupps deployment tools, change it, upload it back and check your changes.
I am new to couchdb so bear with me if this is really easy.
I am trying to prototype a system where there is group of user who can share everything within a database to each other. For example, think of a message board system that once a user is allow into a particular board, they can view/update/delete anything in that message board. Also, a user can join multiple boards.
From what I read so far, the way I am thinking to achieve this is to have multiple database within the couchdb server. Each database represents a board and since board doesn't need to talk to each other, this give a nice separation between boards.
My question is about user authorization. I know that I can create user in couchdb and assign them ACL within one "database", but is there a way in couchdb that it controls user access in a "database" level? ie. which database can a user read/write/update?
the only way I see now is to have another table in a "application" database can control user access, basically a mapping from user to database.
You seem to contradict yourself. You say that you know you can assign a user an ACL within one database, and then you ask if there's a way to control user access in a database.
All authorization is at a database level. Read the Authorization section of the Security docs.
I would like to restrict the user permissions so that a normal user is only able to read/write its own user document.
I managed to set the write permissions such that a user can only edit their own document (via the validate_doc_update function in the design document).
Now I only have to limit a user from viewing the user list or other user documents. If I set the database read permissions to the '_admin' role, then the user will not be able to view their own document, which it's not what I intend.
Can this be done in a more general way? I.e. to set read permissions such that a user is able to read only some specific documents in the database?
Unfortunately, per-document read control is not possible.
However, if you use a list function you can perform a "post-query filter" that limits the results of a view query based on the current session user. (via the userCtx parameter)
In CouchDB creating a new database is cheap and it was designed to keep the data as close as possible to the user who needs it.
So the suggested approach is to have one database for each user.