Having Problems Designing Sign-In / Sign-Up Logic

2020-04-20 07:03发布

I'm relatively new with Android/programming... I'm trying to design an app that uses Firebase as the backend (although the problems I am having would exist for any app that tries to make immediate decisions based on remote data).

I feel like there is a smarter way to do what I'm trying to do.

The requirements are (the way I'm thinking about problem):

  • Design an app where new users sign in and register (two separate things), but the app will not allow them to use the app properly unless they have been expicitly (manually) authorized by a human via the Firebase database console. Existing/approved users will bypass these stages.

So... to solve this, I have thought:

  1. When they first open the app, if they are not signed in, present them with a SignIn Activity.

  2. If, upon successful sign-in, it is found they have not yet registered, then present a registration Activity.

  3. If upon successful registration, it is found that they are not yet admin-approved, then exit the app with an alert dialog explaining they must wait longer for approval.

Sounds simple... so we could just have a MainActivity onResume() method like this:

@Override
protected void onResume(){
    super.onResume();

    // if not signed in, go to signIn/Create account activity

    // (either we are signed in or we return from signin.java)

    // if not signedUP/registered, then we go to signUP/register activity

    // (either we are signed up or we return from register.java)

    //  is user admin-approved?  if not, then we exit.


}

But the problems arise when we try to implement these "checks."

How do you check whether a user has already registered? I thought, well, we can just query the Firebase database... for example:

  • To find out if a user has already registered, we check for a branch (key) in the JSON tree of the Firebase DB that matches the signed in userID, then we know they have registered (because the registration activity would have created this record already)

  • To check whether they are admin-approved, we would check for a field such as:

    '\firebase\user_id\isAllowed' = true. 
    

This field would be set to false by default and set to true only if an admin manually sets the value in the database.

But these sort of remote checks will take time to execute... and the results are delivered via callback methods... so how can we "pause" the onresume method so that it waits for the result before continuing?? (we could 'nest' callbacks within callbacks: Firstcheck.onsuccess() { [Secondcheck.onsuccess() { [Thirdcheck.onsuccess() { // SUCCESS! }] } ] } ... but this seems like a bad idea.

Alright... so why not use shared preferences instead, and have the registration activity save a "user_progress" variable such as 1, meaning that they have completed the registration? This way the user's progress would be stored locally and could be immediately checked in the onresume() logic.

But then this creates a new problem... that is what if the user re-installs the app? then the shared preferences are wiped and it would now believe that they are not registered... and mistakenly present them with the registration activity again.

I have individual solutions for these individual problems, but what results is a rat's nest of hard to follow code...

Has anyone else been stuck with this kind of problem? Where am I going wrong in my thinking? I feel like there is a fundamentally incorrect way that I'm approaching it... like procedural vs object oriented... and I'm wondering if anyone can address that.

1条回答
家丑人穷心不美
2楼-- · 2020-04-20 07:27

Well... since nobody has answered yet, I've still been working on this, and my best solution is:

In the SignINActivity, when the user is successfully signed in, I will save a copy of their datasnapshot (profile) from the Firebase database in Shared Preferences. That way, when they return to the onResume() in MainActivity, it can use this snapshot to determine all the conditions I need without callbacks being involved. Subsequently, in signUPActivity, I will update the local snapshot when that is completed, also.

I have replaced 'MainActivity' with a new launcher class, ActionDecider.

ActionDecider.onResume() :

@Override
protected void onResume(){
    super.onResume();

    // TODO: do safetynet check here


    // (4) CONDITIONS :  HOW TO TELL :  WHAT TO DO
    // 
    // 1)not signed in : auth == null : load SignINActivity
    // 2)signed in, but not registered : snapshot == null : load SignUPActivity
    // 3)registered, but not approved : /userid/isAllowed == false : exit with dialog
    // 4)registered, and approved : /userid/isAllowed == true : continue as normal



    // if not signed in, go to signIn/Create account activity

        // user is sent to signIN which signs them in (or creates account), and saves a
        // datasnapshot of their db tree to shared prefs before returning here


    // (user is signed in)

    // CHECK: is user approved? (check the snapshot -- this is checked first because in 
    // most cases they will be approved, and this avoids an unnecessary extra check)

        // yes?  [exit] and load mainActivity. []

        // no?  CHECK:  is user signed up?

                // no?  load signUP-Activity   (signUP activity UPDATES datasnapshot when complete)

                // yes?  [exit] with dialog 

}

Best solution? I doubt it. But... feel free to let me know a better approach.

查看更多
登录 后发表回答