Querying MongoDB in the Browser with React and Realm
Rate this tutorial
One of the primary reasons database connections are traditionally server-to-server is so that we do not expose any admin credentials. Leaking credentials like this is not a concern with Realm as it has
. There are no admin credentials to expose as each user has a separate account. Then, using Rules, we control what data each user has permission to access.
The MongoDB service uses a
that prevents all operations unless they are specifically allowed. MongoDB Realm determines if each operation is allowed when it receives the request from the client, based on roles that you define. Roles are sets of document-level and field-level CRUD permissions and are chosen individually for each document associated with a query.
Rules have the added benefit of enforcing permissions at the data access level, so you don't need to include any permission checks in your application logic.
We're going to be using one of the sample datasets in this tutorial, so after creating your free cluster, click on Collections and select the option to
. Once the data is loaded, you should see several new databases in your cluster. We're going to be using the
sample_mflixdatabase in our code later.
In your Realm App, go to the Users section and enable the Email/Password provider, the user confirmation method should be "automatic", and the password reset method should be a reset function. You can use theprovided stubbed reset function for now.
In a real-world application, we would have a registration flow so that users could create accounts. But for the sake of this tutorial, we're going to create a new user manually. While still in the "Users" section of your Realm App, click on "Add New User" and enter the email and password you would like to use.
Rules and Roles govern what operations a user can perform. If an operation has not been explicitly allowed, Realm will reject it. At the moment, we have no Rules or Roles, so our users can't access anything. We need to configure our first set of permissions.
Navigate to the "Rules" section and select the
sample_mflixdatabase and the
moviescollection. Realm has several "Permissions Template"s ready for you to use.
- Users can only read and write their own data.
- Users can read all data, but only write their own data.
- Users can only read all data.
These are just the most common types of permissions; you can create your own much more advanced rules to match your requirements.
- Configure a role that can only insert documents.
- Define field-level read or write permissions for a field in an embedded document.
- Determine field-level write permissions dynamically using a JSON expression.
- Invoke a Realm Function to perform more involved checks, such as checking data from a different collection.
We only want our users to be able to access their data and nothing else, so select the "Users can only read and write their own data" template.
Realm does not stipulate what field name you must use to store your user id; we must enter it when creating our configuration. Enter
authorIdas the field name in this example.
By now, you should have the Email/Password provider enabled, a new user created, and rules configured to allow users to access any data they own. Ensure you deploy all your changes, and we can move onto the code.
Once you have the code downloaded, you will need to install a couple of dependencies.
This provider handles the creation of our Realm Web App client, as well as providing methods for logging in and out. Let's look at these parts in more detail.
The value for
REALM_APP_IDis on your Realm App dashboard. We instantiate a new Realm Web App with the relevant ID. It is this App which allows us to access the different Realm services. You can find all required environment variables in the
logInmethod accepts the email and password provided by the user and creates a Realm credentials object. We then use this to attempt to authenticate with our Realm App. If successful, we store the authenticated user in our state.
Just like the Realm App context provider, we're going to be accessing the Atlas service throughout our component tree, so we create a second context provider for our database.
In this React hook, whenever our user variable updates—and is not null, so we have an authenticated user—we set our db variable equal to the database service for the
Once the service is ready, we can begin to run queries against our MongoDB database in much the same way as we would with the Node.js driver.
However, it is a subset of actions, so not all are available—the most notable absence is
collection.watch(), but that is being actively worked on and should be released soon—but the common CRUD actions will work.
The default boilerplate generated by
create-react-appplaces the DOM renderer in
index.js, so this is a good place for us to ensure that we wrap the entire component tree within our
The order of these components is essential. We must create our Realm Web App first before we attempt to access the
mongodb-atlasservice. So, you must ensure that
<MongoDB>. Now that we have our
<App />component nestled within our Realm App and MongoDB contexts, we can query our Atlas cluster from within our React component!
Our demo has two main components: a login form and a table of movies, both of which are contained within the
App.js. Which component we show depends upon whether the current user has authenticated or not.
The login form consists of two controlled text inputs and a button to trigger the handleLogIn function.
The MovieList component renders an HTML table with a few details about each movie, and a button to allow the user to log out.
Here, we have our main
<App />component. Let's look at the different sections in order.
We're going to use the Realm App and the MongoDB provider in this component: Realm App for authentication, MongoDB to run our query. We also set up some state to store our email and password for logging in, and hopefully later, any movie data associated with our account.
This React hook runs whenever our user or db updates, which occurs whenever we successfully log in or out. When the user logs in—i.e., we have a valid user and a reference to the
mongodb-atlasservice—then we run a find on the movies collection.
Notice we do not need to specify the User Id to filter by in this query. Because of the rules, we configured earlier only those documents owned by the current user will be returned without any additional filtering on our part.
If you run the demo and log in now, the movie table will be empty. We're using the sample dataset, and none of the documents within it belongs to our current user. Before trying the demo, modify a few documents in the movies collection and add a new field,
authorId, with a value equal to your user's ID. You can find their ID in the Realm App Users section.
Once you have given ownership of some documents to your current user, try running the demo application and logging in.
Congratulations! You have successfully queried your database from within your browser, no server required!
Try modifying the rules and roles you created to see how it impacts the demo application.
Ignore the warning and delete the configuration for the movies collection. Now, your App should die with a 403 error: "no rule exists for namespace' sample_mflix.movies.'"
Use the "Users can read all data, but only write their own data" template. I would suggest also modifying the
find()or adding a
limit()as otherwise, the demo will try to show every movie in your table!
Add field-level permissions. In this example, non-owners cannot write to any documents, but they can read the title and year fields for all documents.
For more information on MongoDB Realm and the Realm Web SDK, I recommend reading our documentation: