Hi, dear readers! It is time for the second part of the database setup. The first part you can see here. It was about the basic usage of the DB and its creation for your project.
Note: I have created a new DB for this part because rules changes will affect the first part versions of the app. Don’t focus your attention on the other links in the base URLs, just continue your application :)
In this part I want to describe the following topics:
- How to set up the authentification, create signup and login methods
- How to configure rules for the privacy of the DB
- How to query data from the DB
Set up the authentication
Let’s go to the Firebase and set up the authentication for the DB. In the menu choose the authentification route and press get started.
Then you will be offered authentication options. In my case, I want to use auth with email and password, but you can choose either way.
Then set these configurations. DB authentication is ready.
Docs says that we should use
https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]
URL to make a post request to signup the user. Also, you can see, that the request body should use this interface. The returnSecureToken field should always be true.
It is time to code!
The last state of the application looked like this:
To keep our time I have created login and signup components in the auth directory. Also, there is a new service, where we will define auth methods like login, signup, and logout. I’ve filled a header with some new routes and a logout button, added a new AuthReq and AuthRes interfaces for auth methods body type, add new links for signup and login in enviroment.ts and environment.prod.ts files.
Here you can see the updates:
So we have everything we need to get in touch with the DB. Let’s create a signup method in the auth service. To do this you should connect the signup form with authService.
signup.component.ts
Inject authService in the signup component’s constructor, put the form value as a method’s parameter, and subscribe to the signup service like this:
onSubmit() {
this.authService.signup(this.form.value).subscribe(console.log);
}
I will keep console.log in the subscribe method to see the results of the request.
auth.service.ts
In the authService you will get a body that consists of an email and a password. As you remember there was an interface in the Firebase docs, that contains the returnSecureToken field. So we should follow the docs and add this field to the body. Then we make a simple POST request that returns data of the AuthRes interface, which contains an auth token. Let’s store it in the localStorage. It looks like this:
signup(body: AuthReq): Observable<AuthRes> {
body.returnSecureToken = true;
return this.http
.post<AuthRes>(`${environment.authSignup}${environment.apiKey}`, body)
.pipe(tap((res: AuthRes) => this.setToken(res.idToken)));
}
In the console you can see such response, if you will try to sign up:
That’s it!
In a similar way create login method.
Now we have opportunity to create new users and login. The application looks this way:
Configuration DB rules
It’s time to configure the rules of the DB. To do this follow the next steps:
- Go to the Realtime DB and select the rules tab. I want to have an opportunity to read the hero list from the DB without logging, so I just change the “.write” rule and leave the “.read” rule in true.
- Set the “.write” rule “auth !== null” and publish
If you will interact with dB to change it, you get the 401 error. It means that before we change anything, we should get authorized.
To say firebase that we have already logged in and should be able to change the DB, we should set parameters to the request URLs.
In real life, it would be better to make it with the help of interceptors, but now to keep it simple, add the auth parameter to the URLs in the heroesServise, which are used to change the DB. Now the links look as follows:
${environment.db}heroes.json?auth=${this.token}
Success! Everything works now. Check the updates in the hero.service.ts:
Query data from the DB
Well, let’s try to query cards by the search string. I want to say that firebase isn’t very flexible in this question. You can see how to retrieve the data here.
For this tutorial, I offer to search heroes by name. You will see, that the search is case-sensitive. To avoid this, you should store your data, for example, in lowercase and format it on the client side. Also, there is no way to search data by parts (like includes method works). See more info here.
To retrieve data we should update the rules in the DB like this:
Return to the app. I’ve updated it with the searchBar component. It emits a search value to the collection component, in which we will search heroes. Check search-bar.component.ts, collection.component.ts and collection.component.html on updates:
Now on the search event emitted from the searchBar component, I will call the getCollection method with the string as a parameter. Subscribe to it and set response data to this.heroes:
onSearch(string: string) {
this.heroService
.getCollection(string)
.subscribe((data) => (this.heroes = data));
}
Now the app is broken, let’s move to the hero.service to fix it.
I will search heroes by the start of the name. To filter heroes this way we should use these params:
?orderBy=”name”&startAt=”${string}”&endAt=”${string}
In the service in the getCollection method we should pass the optional parameter and make a check inside:
getCollection(string?: string): Observable<Hero[]> {
let url = `${environment.db}heroes.json`;
if (string) {
url = `${environment.db}heroes.json?orderBy="name"&startAt="${string}"&endAt="${string}\uf8ff"`;
}
return this.http.get<Hero[]>(url).pipe(
map((data: { [key: string]: any }) => {
return Object.keys(data)
.map((key) => ({
...data[key],
id: key,
}))
.reverse();
})
);
}
Here you can see the final application:
I hope this short 2 part tutorial will help novice frontend developers to practice backend integration and level up their pet projects.
You can read the previous article here.
Thanks for reading!
Top comments (0)