AngularFire извлекает идентификатор документа на основе аутентификации пользователя - PullRequest
1 голос
/ 23 сентября 2019

Я настраиваю пользовательскую базу данных в firebase, где идентификатор документа будет храниться с использованием идентификатора аутентификации пользователя.

Проблема, с которой я сейчас сталкиваюсь, заключается в хранении текущего пользовательского документа, отображаемого на моей информационной панели при входе пользователя в систему.

В настоящее время на моем authService.ts я храню данныеиз firebase.user, который на моей панели будет отображать только информацию из массива по умолчанию.Это то, что у меня есть в моем auth.service.ts

export class AuthService {
  userData: any; 
  userCollection: AngularFirestoreCollection<User>;
  constructor(

    public afs: AngularFirestore,   // Inject Firestore service
    public afAuth: AngularFireAuth, // Inject Firebase auth service
    public router: Router,  
    public ngZone: NgZone, // NgZone service to remove outside scope warning

  ) {    
    /* Saving user data in localstorage when 
    logged in and setting up null when logged out */
    this.afAuth.authState.subscribe(user => {
      if (user) {
        this.userData = user;
        localStorage.setItem('user', JSON.stringify(this.userData));
        JSON.parse(localStorage.getItem('user'));
        this.UserID = this.userData.uid;
      } else {
        localStorage.setItem('user', null);
        JSON.parse(localStorage.getItem('user'));
      }
    })
  }

  SignUp(username, email, password) {
    return this.afAuth.auth.createUserWithEmailAndPassword(email, password)
      .then((result) => {
        // set account  doc 
          let created_data = JSON.parse(JSON.stringify(result.user));
          const account = {
          uid: result.user.uid,
          created_time: created_data.createdAt,
          email:  result.user.email,
          display_name: username,
          photoURL: result.user.photoURL,
        }
        this.SetUserData(account);
      }).catch((error) => {
        window.alert(error.message)
      })
  }

  /* Setting up user data when sign in with username/password, 
  sign up with username/password and sign in with social auth  
  provider in Firestore database using AngularFirestore + AngularFirestoreDocument service */
  SetUserData(user) {
    const userRef: AngularFirestoreDocument<User> = this.afs.doc(`users/${user.uid}`);
    const userData: User = {
      bio: null,
      country: {
        country: null,
        country_code:null,
        symbol:null
      },
      gender: "unspecified",
      languages: null,
      profile_pic: user.photoURL,
      username: user.display_name,
    }
    return userRef.set(userData, { 
      merge: true
    })
  }
}

и в моем dashboard.component.ts

export class DashboardComponent implements OnInit {

  isLoggedIn$: Observable<boolean>;
  isLoggedOut$:Observable<boolean>;

  constructor(
    public afAuth: AngularFireAuth,
    public authService: AuthService
    ) { }

  ngOnInit() {
    this.isLoggedIn$ = this.afAuth.authState.pipe(map(user => !!user));
    this.isLoggedOut$ = this.isLoggedIn$.pipe(map(loggedIn => !loggedIn));
  }
}

, с этим я могу получить детали только из того, что хранится в firebase.userа не моя настроенная БД.Как мне войти в конкретный документ, основанный на UID аутентифицированного пользователя, чтобы я мог отображать информацию, такую ​​как биография, пол и языки?

вот как я анализирую информацию на моем dashboard.html

<!-- Main content -->
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-4">
  <div class="inner-adjust">
    <div class="pt-3 pb-2 mb-3 border-bottom">
      <h1 class="h2">User Profile</h1>
    </div>
    <!-- Show user data when logged in -->
    <div class="row" *ngIf="authService.userData as user">
        <div class="col-md-12">
        <div class="media">
          <img class="align-self-start mr-5 img-thumbnail rounded-circle" src="{{(user.photoURL) ? user.photoURL : '/assets/placeholder-user.jpg'}}"
            alt="{{user.displayName}}">
          <div class="media-body">
            <h1>Hello: <strong>{{(user.username)}}</strong></h1>
            <p>Email: <strong>{{user.email}}</strong></p>
            <p>Gender: <strong>{{user.gender}}</strong></p>
            <p>Languages: <strong>{{user.languages}}</strong></p>
          </div>
        </div>
      </div>

      <!-- </div> -->
    </div>

  </div>
</main>

1 Ответ

1 голос
/ 23 сентября 2019

Я не вижу соответствующего использования здесь для использования localStorage, firebase будет выдавать authstate, пока приложение работает, и если пользователь не вошел в систему, authState возвращает null.

Кстати - вы также используете JSON.parse(JSON.stringify(...)) в одном месте, что не имеет особого смысла;)

В любом случае, у меня есть похожая настройка, и вот как я это делаю:

в сервисе аутентификации:

user$ = Observable<any>;

this.user$ = this.afAuth.authState.pipe(
  switchMap(user => {
    if (user) {
      return this.afs.doc<any>(`users/${user.uid}`).valueChanges();
    } else {
      return of(null);
    }
  })
);

Тогда я просто подпишусь на user$ там, где мне это нужно.Либо сделайте это, подписавшись вручную или используя async pipe.Если вы хотите подписаться вручную, не забудьте отменить подписку также на уничтожение компонента.

Вот пример использования асинхронного канала:

user$ = Observable<any>;

constructor(private authService: AuthService) { }

ngOnInit() {
  this.user$ = this.authService.user$;
}

Шаблон:

<div *ngIf="(user$ | async) as user">
   <h1>Hello: <strong>{{(user.username)}}</strong></h1>
</div>

Также, НЕ используйте any.Пожалуйста, создайте модели (интерфейс мой выбор) для ваших данных.Мы работаем с Type Script в конце концов;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...