Я хочу ограничить данные, к которым пользователь может получить доступ, на основе свойства accountId профиля пользователя в Firestore, accountId устанавливается при создании нового пользователя.
Я использую Angular 6, Rxjs, Ngrxи AngularFire2.
Я изо всех сил пытаюсь найти лучший способ сделать это и рассмотрел следующее:
- Установить AccountId в локальном хранилище.Это работает, но не очень безопасно
- Установите фильтр в моей службе пожарной охраны.
Это мой предпочтительный вариант, так как я могу установить его в одном месте и всегда знать, что пользователь может получить доступ только к соответствующим данным
Каждый документ, записанный в базу данных firestore, всегда имеет currentUsersaccountId, записанный в качестве свойства в документе
Когда я пытаюсь выбрать предпочтительное решение, я получаю accountId не определено, однако, когда я захожу в свою базу данных firestore, у пользователя есть accountId, а когда я захожу в свой ngrx, пользователь имеетaccountId.
Похоже, что это проблема синхронизации, но вы не знаете, как всегда гарантировать, что при входе в систему не будет запросов к базе данных, пока не будет доступен идентификатор учетной записи пользователя.
Показ моей консоли.logзапрос firestore выполняется до запуска подписки в конструкторе firestore
import { Injectable } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore';
import { Observable } from 'rxjs/Observable';
import { fromPromise } from 'rxjs/observable/fromPromise';
import { of } from 'rxjs/observable/of';
import { expand, takeWhile, mergeMap, take, catchError } from 'rxjs/operators';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/take';
import 'rxjs/add/operator/do';
import * as firebase from 'firebase/app';
import { AuthService } from '@core/services/auth.service';
import { User } from '../../shared/models';
import { from, throwError } from 'rxjs';
type CollectionPredicate<T> = string | AngularFirestoreCollection<T>;
type DocPredicate<T> = string | AngularFirestoreDocument<T>;
@Injectable()
export class FirestoreService {
colRef: any;
user: User;
currentUser: User;
currentUser$: Observable<any>;
constructor(
public afs: AngularFirestore,
private authService: AuthService,
) {
this.authService.user.subscribe(res => {
this.user = res;
if (this.user) {
this.currentUser$ = this.afs
.collection('users', ref => ref.where('id', '==', this.user.id))
.valueChanges();
}
this.currentUser$.subscribe(user => {
this.currentUser = user;
console.log('Constructor:', this.currentUser);
});
});
}
/// **************
/// Get a Reference
/// **************
col<T>(ref: CollectionPredicate<T>, queryFn?): AngularFirestoreCollection<T> {
return typeof ref === 'string' ? this.afs.collection<T>(ref, queryFn) : ref;
}
/// **************
/// Get Data - NGRX Effects makes a call to this method
/// **************
col$<T>(ref: CollectionPredicate<T>, queryFn?): Observable<T[]> {
return this.col(ref, queryFn)
.snapshotChanges()
.map(docs => {
return docs.map(a => a.payload.doc.data()) as T[];
});
}
/// with Ids
colWithIds$<T>(ref: CollectionPredicate<T>, queryFn?): Observable<any[]> {
if (queryFn === undefined) {
if (this.currentUser) {
console.log('Firestore Query:', this.currentUser);
queryFn = reference => reference.where('accountId', '==', this.currentUser.accountId);
}
}
console.log('FireStore Query');
return this.col(ref, queryFn)
.snapshotChanges()
.map(actions => {
return actions.map(a => {
const data: any = a.payload.doc.data();
const id = a.payload.doc.id;
return { id, ...data };
});
});
}
}