Я кодирую код ниже, который уведомляется в режиме реального времени. Я имею в виду, что он продолжает наблюдать, и вскоре все поля коллекции обновляются, он загружается на страницу Angular.
app.component.ts
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { AngularFirestore } from '@angular/fire/firestore';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
public transfers: Observable<any[]>;
constructor(db: AngularFirestore) {
this.transfers = db.collection('/transfer').valueChanges();
}
}
app.component. html
<code><ul>
<li *ngFor="let transfer of transfers | async">
<pre>{{ transfer | json }}
Моя проблема является то, что я не знаю, как добавить idToken при наблюдении либо с помощью db.collection (). valueChanges () или snapshotChanges (). Что ж, я знаю, как генерировать idToken вне приложения из пользовательского токена, и для этого вопроса я хочу сосредоточиться только на том, как добавить такой idToken при «прослушивании» valueChanges () или snapshotChanges () указанного c документа. Представьте, что каждый документ представляет собой отдельную транзакцию, интересующую только одного пользователя.
Приведенный выше код работает, как и ожидалось, если я изменю правила Firestore на «разрешить чтение всем», но я хочу найти способ разрешить только Angular читать, если он проходит через idToken, и, кроме того, наблюдать за изменениями в одном документе вместо того, чтобы наблюдать за всеми документами из всей коллекции, как это делает код выше.
Вот некоторые предварительные предположения, проваливающиеся просто для иллюстрации того, что я пытаюсь сделать. Я не знаю, как добавить idToken в любой из них. Я добавил также пример того, что, по моему мнению, может работать без AngularFire. Я предполагаю, что меня смущают три момента:
какая-то очень базовая c идея, как наблюдать / прослушать один документ
как добавить idToken, похожий на то, как я делаю с curl / postman
, невозможно прослушать / наблюдать один документ. Я должен наблюдать всю коллекцию и фильтр.
Предварительно 1:
this.uniqueTransfer = db.collection('/transfer',
ref => ref.where("id", "==", "1"))
.snapshotChanges().pipe(map(actions => actions.map(a => a.payload.doc.data()))
);;
Предварительно 2:
this.uniqueTransfer = db.collection('/transfer', ref => ref.where("id", "==", "1")).snapshotChanges().pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data();
return { data };
}))
Предварительно 3:
db.doc(`transfer/Wsj0dysyHHok3xupwDhD`) //this is the id copied from Firebase console
.snapshotChanges()
.pipe()
.subscribe();
Предварительно 4 без AngularFire
constructor(private http: HttpClient) {
this.getTranfers();
}
public getTranfers() {
const headers = { 'Authorization': 'valid idtoken working with curl' }
const body = JSON.stringify({
"structuredQuery": {
"where": {
"fieldFilter": {
"field": { "fieldPath": "id" },
"op": "EQUAL",
"value": { "stringValue": "4" }
}
},
"from": [{ "collectionId": "transfer" }]
}
})
this.http.post<any>('https://firestore.googleapis.com/v1/projects/firetestjimis/databases/(default)/documents:runQuery', body, { headers }).subscribe(data => {
this.uniqueTransfer = data;
})
}
И ожидаемое поведение - прослушивание для изменения документа especifi c и обновление внешнего интерфейса, например:
<div>{{(uniqueTransfer|async)?.status}}</div>
Наконец, в случае добавления здесь, я можно запросить один документ с этим curl. Obvisouly это не слушать / наблюдать документ. Он просто получает его.
curl --location --request POST 'https://firestore.googleapis.com/v1/projects/firetestjimis/databases/(default)/documents:runQuery' \
--header 'Authorization: Bearer certain idToken resulted from a Custom Token' \
--header 'Content-Type: application/json' \
--data-raw '{
"structuredQuery": {
"where" : {
"fieldFilter" : {
"field": {"fieldPath": "id"},
"op":"EQUAL",
"value": {"stringValue": "1"}
}
},
"from": [{"collectionId": "transfer"}]
}
}'
*** отредактировано После двух предложений gso_Gabriel.
FIRST SUGGESTION)
Я пытался следовать https://github.com/angular/angularfire/issues/2109 , Что ж, похоже, это предложение для новой функции, а не действующая альтернатива. Кстати, я дал попробовать с:
this.transfers = db.doc<any>(`transfer/sDme6IRIi4ezfeyfrU7y`).valueChanges();
sDme6IRIi4ezfeyfrU7y обозначает конкретный c документ, но я получил все документы из коллекции передачи (такое же поведение, как this.transfers = db.collection ('/ Transfer' ) .valueChanges ();)
ВТОРОЕ ПРЕДЛОЖЕНИЕ)
import { map } from 'rxjs/operators';
import 'rxjs/Rx';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
public transfers: Observable<any[]>;
uniqueTransfer: any;
transferCollectionRef: AngularFirestoreCollection<any>;
constructor(db: AngularFirestore) {
this.transferCollectionRef = db.collection<any>('transfer', ref => ref.where("id", "==", "1"));
this.transfers = this.transferCollectionRef.snapshotChanges().map(actions => {
return actions.map(action => {
const data = action.payload.doc.data();// as Todo;
const id = action.payload.doc.id;
return { id, ...data };
});
});
}
Это сработало. Я вижу фильтр "где" применяется (... ref => ref.where ("id", "==", "1")
Теперь мне не хватает как использовать полученный idToken от Custom Tokem. Я думаю, что он должен существовать каким-то образом, как мы делаем с HttpClient (см. мой предварительный 4 выше, чтобы понять, что является общим подходом с заголовком).
*** В случае, если это добавить как-то здесь, даже аналогичные вопрос, размещенный на github, не получил никакого комментария, кроме того, что кто-то говорит, что ищет тот же ответ https://github.com/angular/angularfire/issues/2419
*** ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ СПАСИБО gstvg
export class AppComponent {
public transfers: Observable<any[]>;
transferCollectionRef: AngularFirestoreCollection<any>;
constructor(public auth: AngularFireAuth, public db: AngularFirestore) {
this.listenSingleTransferWithToken();
}
async listenAllTransfersWithToken() {
await this.auth.signInWithCustomToken("eyJh...w8l-NO-rw");
this.transfers = this.db.collection('/transfer').valueChanges();
}
async listenSingleTransferWithToken() {
await this.auth.signInWithCustomToken("eyJ...w8l-NO-rw");
this.transferCollectionRef = this.db.collection<any>('transfer', ref => ref.where("id", "==", "1"));
this.transfers = this.transferCollectionRef.snapshotChanges().map(actions => {
return actions.map(action => {
const data = action.payload.doc.data();
const id = action.payload.doc.id;
return { id, ...data };
});
});
}
}