3

I implemented angular firebase email and password registration and login, but now what I want to do is check in my navigation template the state of the user, if the user is logged in, then hide login button, as well as hide register button. I tried googling for some tutorials on this, and found out that I must use AuthService and AuthInfo as you can see here:

https://github.com/angular-university/angular-firebase-app/blob/master/src/app/shared/security/auth.service.ts

The thing is that they are using a lot of promises and stuff, which I'm not familiar with and it really confuses me. I'm trying to achieve this in the most basic way and looking for someone to guide me and help me.

Here is my code now:

navigation -

<ul class="nav navbar-nav">
    <li><a routerLink="" routerLinkActive="active">Home</a></li>
    <li><a routerLink="login" routerLinkActive="active" *ngIf="!authInfo?.isLoggedIn()">Login</a></li>
    <li><a routerLink="register" routerLinkActive="active" *ngIf="!authInfo?.isLoggedIn()">Register</a></li>
    <li><a routerLink="quiz" routerLinkActive="active">Quiz</a></li>
</ul>

My Auth service file with all the user create and login to firebase logic -

@Injectable({
    providedIn: 'root'
})
export class AuthService {
    private user: Observable<firebase.User>;
    constructor(private _firebaseAuth: AngularFireAuth, private router: Router) {
        this.user = _firebaseAuth.authState;

        this.user.subscribe(
            (user) => {
                if (user) {
                    this.userDetails = user;

                    console.log(this.userDetails);
                } else {
                    this.userDetails = null;
                }
            }
        );
    }

    logUserIn(email, pass) {
        firebase.auth().signInWithEmailAndPassword(email, pass).catch(function (error) {
            // Handle Errors here.
            var errorCode = error.code;
            var errorMessage = error.message;
            console.log("error" + error);
        })

        if (this.userDetails) {
            email = this.userDetails.email;
            console.log("hello im user" + " " + email);

        } else {
            console.log("not working");
        }

        this.router.navigate(['']);
    }

    regUser(email, pass) {
        firebase.auth().createUserWithEmailAndPassword(email, pass)
            .catch(function (error) {
                // Handle Errors here.
                var errorCode = error.code;
                var errorMessage = error.message;

            });
    }
}

Login component -

@Component({
    selector: 'login',
    templateUrl: 'login.component.html'
})
export class LoginComponent {

    form: FormGroup;

    constructor(fb: FormBuilder, private _loginService: LoginService, private auth: AuthService) {

        this.form = fb.group({
            email: ['', Validators.required],
            password: ['', Validators.compose([Validators.required,
            PasswordValidator.cannotContainSpace])]
        })

    }

    login() {
        this.auth.logUserIn(this.form.value.email, this.form.value.password);
    };
}

auth-info.ts file from the github link above -

export class AuthInfo {

    constructor(public $uid: string) { }

    isLoggedIn() {
        return !!this.$uid;
    }
}

EDIT:

So thanks to Tushar Walzade I managed to show and hide these buttons, but I get really weird behaviour. There are no problems when logging out, but when I login, nothing happens, I get not working message to Chrome console which comes from my logUserIn method in Auth service. But when I refresh page one time, then it shows me that it's working, I get user information details in console and buttons get hidden. I don't know why this happens, but I think this might be something with sessionStorage which I know nothing about.

Here is the code:

Auth service

export class AuthService {
  private user: Observable<firebase.User>;
  private userDetails: firebase.User = null;
  public loggedIn = false;



  constructor(private _firebaseAuth: AngularFireAuth, private router: Router) {
    this.user = _firebaseAuth.authState;
    this.loggedIn = !!sessionStorage.getItem('user');

    this.user.subscribe(
        (user) => {
          if (user) {
            this.userDetails = user;

            console.log(this.userDetails);
          } else {
            this.userDetails = null;
          }
        }
      );
  }

  // Set current user in your session after a successful login
    setCurrentUser(email: string): void {
        sessionStorage.setItem('user', email);
        this.loggedIn = true;
    }

    // Get currently logged in user from session
    getCurrentUser(): string | any {
        return sessionStorage.getItem('user') || undefined;
    }

    isLoggedIn() {
    return this.loggedIn;
    }

  logUserIn(email, pass) {
    firebase.auth().signInWithEmailAndPassword(email, pass).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
console.log("error" + error);
})
//var user = firebase.auth().currentUser;
//var email;
if (this.userDetails) {
email = this.userDetails.email;
console.log("hello im user" + " " + email);
//email = user.email;
this.setCurrentUser(email);
 this.loggedIn = true;
} else {
console.log("not working");
}

this.router.navigate(['']);
}

  regUser(email, pass) {
    firebase.auth().createUserWithEmailAndPassword(email, pass)
 .catch(function(error) {
   // Handle Errors here.
   var errorCode = error.code;
   var errorMessage = error.message;
   // ...
 });
//console.log(this.form.controls['email'].value);
    }

    logOut() {
      this.loggedIn = false;
      firebase.auth().signOut().then(function() {
        // Sign-out successful.
        console.log("signout successful");
    }).catch(function(error) {
        // An error happened.
        console.log("error happened");
      });
    }

  }

Login component

export class LoginComponent {

form: FormGroup;

constructor(fb: FormBuilder, private _loginService: LoginService, private auth: AuthService){

    this.form = fb.group({
        email:['',Validators.required ],
  password:['',Validators.compose([Validators.required,

PasswordValidator.cannotContainSpace])] })

}

login(){
      this.auth.logUserIn(this.form.value.email, this.form.value.password);

};

}

app.component.ts because I have my router outlet and links in app.component.html

export class AppComponent {

  title = 'angular-draganddrop';
  constructor(private auth: AuthService) { }
  LoggedIn() {
      return this.auth.isLoggedIn();
  }
  logout() {
    return this.auth.logOut();
  }
}

EDIT EDIT:

So I checked application session storage in Chrome and when I log out I indeed see my user email still there. I have to delete it by hand. Then when trying to log in first time it doesn't work and there is also no user email in session storage. Second time it gets added. The login system was working fine until adding sessionStorage functionality to code so it's definitely related to it. I don't know how sessionStorage works so I'm looking for a help to solve this.

Limpuls
  • 856
  • 1
  • 19
  • 37

2 Answers2

2

You'll need to use session, so that you can check it considering page refreshes.

Just set & use a property for loggedIn as follows in your service AuthService -

public loggedIn = false;

constructor(private _firebaseAuth: AngularFireAuth, private router: Router) {
    this.loggedIn = !!sessionStorage.getItem('user');
}

// Set current user in your session after a successful login
setCurrentUser(email: String): void {
    sessionStorage.setItem('user', email);
    this.loggedIn = true;
}

// Get currently logged in user from session
getCurrentUser(): string | any {
    return sessionStorage.getItem('user') || undefined;
}

// Clear the session for current user & log the user out
logout() {
    sessionStorage.removeItem('user');
    this.loggedIn = false;
    // ... other code for logout
}

// The method to check whether user is logged in or not
isLoggedIn() {
    return this.loggedIn;
}

So, your updated logUserIn method would be -

logUserIn(email, pass) {
    firebase.auth().signInWithEmailAndPassword(email, pass).catch(function (error) {
        // Handle Errors here.
        var errorCode = error.code;
        var errorMessage = error.message;
        console.log("error" + error);
    })

    if (this.userDetails) {
        email = this.userDetails.email;
        console.log("hello im user" + " " + email);
        // setting user in session here --->
        this.setCurrentUser(email);
    } else {
        console.log("not working");
    }

    this.router.navigate(['']);
}

And while logging out, simply call the logout() as shown above.

Then simply add it to your HTML as -

<li><a routerLink="login" routerLinkActive="active" *ngIf="!auth.isLoggedIn()">Login</a></li>
Tushar Walzade
  • 3,737
  • 4
  • 33
  • 56
  • Thanks. Logout works for me. There is something happening weird with login I need to login two times for it to work. First I get "not working" console message in Chrome which comes from my `logUserIn` function in auth service. Console show the errors: `src/app/services/auth.service.ts(17,3): error TS2393: Duplicate function implementation.` `src/app/services/auth.service.ts(28,18): error TS2339: Property 'userDetails' does not exist on type 'AuthService'.` `src/app/services/auth.service.ts(40,40): error TS2345: Argument of type 'String' isnot assignable to parameter of type 'string'. ` – Limpuls Dec 07 '18 at 14:09
  • I will update my question with the new code in a moment – Limpuls Dec 07 '18 at 14:13
  • It seems like you've not declared `userDetails` in your service. Please declare it as - `userDetails: any;` – Tushar Walzade Dec 07 '18 at 14:13
  • Yes, that's what was happening. Anyway, I still witness some weird behaviour. I updated my OP, if you can, please check it. Thanks. – Limpuls Dec 07 '18 at 14:59
  • I see you using `sessionStorage.setItem()`. Do I also aswell need to clear it after logout? – Limpuls Dec 07 '18 at 15:29
  • It looks like async problem. I log my user in with firebase API `firebase.auth().signInWithEmailAndPassword()` and print out userDetails which is bservable. But it takes a while for it to show up in console. Because of this I also get email undefined which comes from userDetails.email observable. Now when finally I see userDetails printed out in the console, I can login one more time (even though I'm logged in already) and then everything works fine. How do I get around this? – Limpuls Dec 08 '18 at 14:07
  • try assigning data to your `userDetails` on successful login (in `.then()`) – Tushar Walzade Dec 09 '18 at 09:20
1

There's a simpler way to do this. See the official github writeup here: https://github.com/angular/angularfire/blob/master/docs/auth/getting-started.md

All you need to do is...

myPage.component.ts

import { AngularFireAuth } from '@angular/fire/auth';
//...
constructor(public afAuth: AngularFireAuth) { }

myPage.component.html

<div *ngIf="(afAuth.user | async)">User is logged IN</div>
<div *ngIf="!(afAuth.user | async)">User is logged OUT</div>
Ryan Loggerythm
  • 2,877
  • 3
  • 31
  • 39