Blog

All Blog Posts  |  Next Post  |  Previous Post

Introduction to using Firestore and new Firestore features in TMS WEB Core v1.7

Bookmarks: 

Monday, April 19, 2021

This article is the first in a 4 part series that will explore the new features available in the TWebFirestoreClientDataSet component in TMS Web Core v1.7.


A quick summary of the basic features in the previous version of Firestore ClientDataSet component

 Here's a quick introduction for those developers who have not had a chance to use the component so far.

 TWebFirestoreClientDataSet was introduced in TMS Web Core v1.3 to enable the developers to use Google Firestore as a cloud-hosted, NoSQL database for their web apps. By using this component, you can use a Google Firestore collection as a dataset and get a full CRUD functionality to update it. As you make changes to the dataset, the component updates the Firestore collection behind the scenes. What is more, since the component is a ClientDataSet, you can bind the component to various DB-aware TMS WEB Core UI controls via a TWebDataSource.

 

Here are the steps to use a Firestore collection as a dataset:

  1. In order to connect to a Firestore collection, all you have to do is drop a TWebFirestoreClientDataSet component on a form and set a few Firebase properties and CollectionName in it. Then define the dataset fields either in design view or in code and make the component Active.
  2. Additionally, you can bind the component to various DB-aware TMS WEB Core UI controls via a TWebDataSource. What you get is a basic App with a CRUD functionality out-of-the-box. A Firestore collection is created automatically as soon as you insert the first record. Any dataset updates you make in code or via the DB-aware controls are automatically sent to Firestore collection by the component.
  3. Further, the basic authentication of a Google Sign-In is also available in the component so that you can force the user to Sign-In with Google before the data in the Firestore collection can be accessed. This requires a simple Authentication rule to be set up in the Firestore dashboard. Then all you need to do in the component is switch ON its property SignInIsRequired. It takes care of presenting a Google Sign-In popup as soon as you make the dataset active.


Complete details for the above steps are given in the TMSWeb Core Firestore documentation.

You will also find a TodoList Demo in the folder "Demo\DBBackend\Firestore" that demonstrates the above features. Please follow the instructions in the TMS Web Core Firestore documentation to set up and run this Demo.

 

Here is a screenshot of the demo:

TMS Software Delphi  Components

What you will see in action is a web app that displays the Task records from a Firestore collection called "Tasks" and provides the features to edit the data by means of various DB-aware controls bound to the data source. It also prompts for a Google Sign-In if the user is not signed in.

Although the basic demo does a good job of showing the CRUD features, it has some problems in the way its start up logic is coded and there is a reason for it as explained below.

  • The demo expects the end user to enter the API Key and other Firebase parameters
  • The values for these parameters are used to set Firebase properties in the Firestore ClientDataSet after the Open button is clicked
  • The values are remembered in the local storage to be used in the next session

 

The reason the basic demo is coded this way is for the convenience of you as a developer when setting up Firebase for the first time. The API Key or some other parameter may not work as you learn the process of set up. Hence, it gives entry boxes for you to experiment till you get them right and remembers the parameters for the next session.

 

But this is not the way a real Web App will work!

Please do not follow the above model for your own web app that uses Firestore ClientDataSet.

 

Here is an attempt to explain why the above approach in the basic demo is wrong and should not be taken as sample code for your own web app:

  • In reality, a web app should never prompt for the Firebase parameters from the user. Setting them belongs in the code or in the object inspector. For the same reason, the Firebase parameters are not remembered in the local storage as they are not prompted for.
  • The App should subscribe to Firebase sign-in events as soon as it starts in order to know whether a user is already signed-in. This is to give a good start up experience to the user. And the Subscribe method needs the Firebase parameters to be set so they can not be postponed to be set later on a button click as the basic demo does.


If you see the new Multi-Tenant Demo described later, it follows the correct approach of setting up these parameters in the code and getting the status of the signed-in user to open the dataset automatically. Also it remembers the Email address of the user in local storage which is convenient for the user.

 

New Sign-In features in the Firestore ClientDataSet component

In this part 1 of the series, we take a look at the new Sign-In related features. There are plenty of them.

 

Sign-In by Email/Password is now supported

The earlier version of the Firestore ClientDataSet Component only supported Google Sign-In method. Many users do not want to sign up for web apps with their Google Sign-In. They prefer to sign up with a custom email address and password for privacy reasons. Hence, the Email/Password method of Firebase Sign-In is popular with web apps as it gives them a complete control over authentication right up to the reset password feature often needed by users.

Your TMS Web Core App can support the Email/Password Sign-In method of Firebase by using the following features of the TWebFirestoreClientDataSet component.

 

Enable Email/Password Sign-In method in Firebase Console first

  •  First of all, you need to enable the Email/Password Sign-In method in the authentication section of the Firebase console.

 

Let the user Sign-Up

  •  Use your own interface in the web app to collect the sign-up email address and password from the user
  • Call the method SignInAsync with the given email and password. Pass a True value for the IsSignUp flag.

 

The suffix "Async" of the method name "SignInAsync" means that you can get the success or failure result of the call by passing an anonynous response procedure to the method. Here is the sample code.

 

    fireStoreClientDataSet.SignInAsync(
        aUserEmail, 
        aPassword,
        True, // IsSignup flag
 
        procedure(success: Boolean; errorName, errorMsg: String)
        begin
            // do something on success or failure
        end
    ); 

 

Let the user Sign-In

  •  Use your own interface to collect the sign-in email address and password from the user
  • Call the same method SignInAsync with the given email, password and a False value for the IsSignUp flag.

 

Let the user Reset Password

  •  To provide this functionality in the App, call the method SendPasswordResetEmail. This tells Firebase to send an Email to the user with a special link to reset the password. You can customize the contents of this email in the Firebase console.

 

fireStoreClientDataSet.SendPasswordResetEmail(

         aUserEmail,

         procedure(success: Boolean; errorName,

            errorMsg: String)

       begin

         if not success then

         begin

           showmessage(errorMsg);

           exit;

         end;

         ... Success actions like

         ... asking the user to check email

         ... and follow the instructions

       end

    );

 

It's good to know that the Firebase Console also helps manage the users

  • In addition to the above features given by the component, you get the features to manage the users in the Firebase console too. There, you can see the list of Users in the Authentication section from where you can disable a user, delete a user or even initiate a reset password for the user.

 

Getting the Signed-In status and acting on it is now easier

 

The features to get the Signed-In status are needed in order to present a better interface to the user who may want to remain signed in.

 

Better example of using SubscribeToSignInEvents

The previous version of TWebFirestoreClientDataSet component already had a method SubscribeToSignInEvents that allows you to get a Sign-In event whenever a user signed in or signed out of your web app. This method enables the web app to change the user interface according to the Signed-In status. But as already explained earlier, the basic TodoList demo does not use this feature properly because it prompts for the Firebase parameters and calls SubscribeToSignInEvents only after a successful Sign In.

In reality, a web app will not prompt for firebase parameters and would rather set them during the initialization of the App. Also the App would then immediately call the SubscribeToSignInEvents method to let a common OnSignInChange event change the interface accordingly.

For example, an App may hide the Sign-In panel and display the Signed-In user's identity. This way the App can change its user interface to show a Signed-In state. The new Firestore Multi-Tenant Demo (folder Demo\Services\Firestore) has the proper sample code that demonstrates this approach.

 

The Sign-In panel in the new Multi-Tenant Demo

TMS Software Delphi  Components

 

In this demo, the Sign-In panel appears only if the user is not signed in.

 

![alt SignIn Panel in the Multi-Tenant Demo](./SigninPanel.png "SignIn Panel in the Multi-Tenant Demo")

 

How the interface changes after Sign In is described in the next section along with a screenshot.

To see the exact implementation, please see the code and comments in the Firestore Multi-Tenant Demo (folder Demo\Services\Firestore). Please note that this is just an example. It's up to you how you prompt for Sign-In credentials. You can even design your own Modal popup to ask for that.

 

GetSignedInUserAsync Method to take one-time actions

If you have used the Sign-In event feature in the previous version, you may have realized that a Sign-In event may occur multiple times for a web app whenever a user signs in and out of web app. Hence, it does not give you a clean way to do something only once if the user is already signed in. 

For example, assume that a user Email is remembered from the last session in local storage. On startup, the App finds that the same user is already logged in to Firebase. In this case, it can open the dataset automatically to give the user a nice start up experience. 

For this purpose, you can use the method GetSignedInUserAsync that gives you the user information of the signed-in user through the anonymous procedure that you pass to it. 

Here is the sample code from the new Firestore Multi-Tenant Demo (folder Demo\Services\Firestore). It automatically opens the dataset if the same user who intends to sign-in is already signed in.

 

  fireStoreClientDataSet.GetSignedInUserAsync(

      procedure(isSignIn: Boolean; UserName: String; UserEmail: String)

      begin

        if isSignIn then

        begin

          if (edEmail.Text <> '') and SameText(edEmail.Text, UserEmail) then

            openDatabase;

        end;

      end

    );


The Multi-Tenant Demo after the user Signs In

TMS Software Delphi  Components

Once the Sign-In occurs or if the user is already found Signed In by the App at start up, the following screen appears where the Sign-In panel is hidden and another control panel appears. Notice how the Signed-In user's email is shown and a Sign-Out button is provided. User may or may not Sign Out when closing the browser. Next time when the user starts the App, it is smart enough to detect a signed in status and open the dataset automatically.

![alt User has Signed In](./SignedInStatus.png "User has Signed In")

 

To see how this approach is implemented, please see the code and comments in the Firestore Multi-Tenant Demo folder Demo\Services\Firestore).

 

Letting the user Sign-Out

To Sign Out of Firebase, you need to call the SignOut method of the component. But you need to close the dataset before you do that otherwise it will generate a usage error. SignOut does not do a close automatically. It depends on the App to close prior to sign-out because only the App knows its proper state whether it is safe to close.

 

Summary of what we learned in this article

  • First, we had a brief look at the basic features of Firestore ClientDataSet component for those of you who haven't had a chance to use it.
  • Next we described the new Sign-In related features of the component that give you the popular Email/Password authentication of Firebase out-of-the-box by the use of a simple flag.
  • We also discussed the proper approach to detect a signed-in user in order to provide a nice user experience.
  • Then we looked at the new Multi-Tenant Demo that uses these new sign-in features in the recommended way.


In the next part 2 of this series, we are going to take a look at the Multi-Tenant capability of the Firestore ClientDataSet component that allows to keep the data of each signed-in user separate and safe.




Masiha Zemarai


Bookmarks: 

This blog post has not received any comments yet.



Add a new comment

You will receive a confirmation mail with a link to validate your comment, please use a valid email address.
All fields are required.



All Blog Posts  |  Next Post  |  Previous Post