我对实时通知的代码进行了编码。我的意思是,它一直在观察,很快任何集合字段都会被更新,它会被加载到角度页面中。
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
<ul>
<li *ngFor="let transfer of transfers | async">
<pre>{{ transfer | json }}</pre>
</li>
</ul>我的问题是,我不知道如何添加idToken,同时使用db.collection()、.valueChanges()或snapshotChanges()进行观察。嗯,我知道如何从自定义令牌在应用程序之外生成idToken,对于这个问题,我只想关注如何在“侦听”特定文档的valueChanges()或snapshotChanges()的同时添加这样的idToken。假设每个文档都是一个只对单个用户感兴趣的不同事务。
如果我将Firestore规则更改为“允许对所有人读取”,则上面的代码可以正常工作,但我希望找到某种方式,如果它通过idToken,只允许角度读取,并且在此基础上,观察单个文档的更改,而不是像上面的代码那样观察整个集合中的所有文档。
这里有一些触须,只是为了举例说明我在尝试什么。我不知道如何在其中任何一个中添加idToken。我还添加了一个我想象的没有AngularFire的例子。我想我对以下三点感到困惑:
,
,
暂定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();不含AngularFire的暂定4
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;
})
}预期的行为是侦听一个特定的文档被更改并更新前端,例如:
<div>{{(uniqueTransfer|async)?.status}}</div>最后,如果它在这里添加,我可以使用这个curl查询单个文档。很明显,它不是在听/看这份文件。它只是收回了它。
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的两项建议。
第一项建议)
我试着跟着https://github.com/angular/angularfire/issues/2109。这似乎是对新特性的建议,而不是目前的一种选择。顺便说一句,我试过:
this.transfers = db.doc<any>(`transfer/sDme6IRIi4ezfeyfrU7y`).valueChanges();sDme6IRIi4ezfeyfrU7y表示特定文档,但我从transfer集合中获得了所有文档(与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.where("id","==","1")
现在,我错过了如何使用自定义Tokem产生的idToken。我想它必须以某种方式存在,就像我们对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 };
});
});
}
}发布于 2020-05-01 20:56:56
防火墙客户端auth由firebase auth处理,因此,要进行身份验证调用,必须使用firebase.auth.signinWithCustomToken(customToken):在后端生成自定义令牌,在前端使用firebase auth进行身份验证。
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { AngularFireAuth } from '@angular/fire/auth';
import { auth } from 'firebase/app';
import { AngularFirestore } from '@angular/fire/firestore';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
public transfers: Observable<any[]>;
constructor(db: AngularFirestore, public auth: AngularFireAuth) {
await auth.signinWithCustomToken(customToken);
this.transfers = db.collection('/transfer').valueChanges();
}
}https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signinwithcustomtoken
https://github.com/angular/angularfire/blob/master/docs/auth/getting-started.md
https://stackoverflow.com/questions/61355351
复制相似问题