如何检查客户的联系人是否正在使用我的应用程序?
How to check if client's contacts are using my app?
我目前正在使用 Firebase 开发应用程序。
我的 Firestore 数据库如下所示:
用户通过 Firebase 身份验证程序后,我将创建一个包含字段“Phone:”的用户文档,其中包含他的 phone 号码。基本上,所有要使用该应用程序的人都会在数据库中列出。
这是我的挑战:
我正在使用插件 easy_contact_picker 将用户设备的所有联系人存储到列表中。
我如何知道用户联系人是否正在使用该应用程序或他们是否在数据库中列出?
我的目标是创建一个显示我所有联系人的联系人列表小部件。但那些正在使用该应用程序或在数据库中列出的联系人应特别突出或标记。
如果我们考虑数据库中列出了数百万用户(以最小化计算能力),那么实现这一点的最佳方式是什么?
有人有想法吗?
非常感谢
首先尽量避免让每个人都可以阅读所有用户。这是大多数人在处理此类问题时所做的事情。这样做是因为如果您不授予阅读所有用户的权限,则对所有用户的查询将无法工作。
出于安全原因,我会将检查用户是否存在的逻辑移动到可调用函数(不是 http 函数!)中。这样您就可以在您的应用程序内部调用它并检查数组中的单个用户或多个用户。这将取决于您的前端如何处理它。
非常重要,而且将以完全相同的格式存储所有 phone 数字。这样你就可以查询它们。无论有多少用户,您总能像这里一样找到特定用户:
var citiesRef = db.collection("users");
var query = citiesRef.where("Phone", "==", "+4912345679");
数字必须完全相同,不能有任何空格 -
字符,+49 或 0049 也必须相同。
您可以创建两个可调用函数。一个检查您的应用程序中是否存在单个用户,另一个检查您发送一个 phone 数字数组并返回一个数组。云函数可以使用 Promise.all
并行执行此类查询,因此您可以获得非常快的响应。
我正在使用类似的方法将我的应用程序中的用户添加为特定组的管理员,您只需在其中输入用户的电子邮件,如果他在应用程序中,他将被添加。我不是他在电子邮件中收到加入应用程序的邀请。
在 Tarik 的回答的帮助下,Ayrix 和我想出了以下解决方案。
重要提示:阅读 Tarik 的回答以获取更多信息。
客户: callable_compare_contacts.dart
import 'package:cloud_functions/cloud_functions.dart';
Future<List<Object>> getMembersByPhoneNumber(List<String> allPhoneNumbers) async {
HttpsCallable callable = FirebaseFunctions.instance.httpsCallable('membersByPhoneNumber');
final results = await callable.call(<String, dynamic>{'allPhoneNumbers': allPhoneNumbers});
return results.data;
}
服务器: index.js
const functions = require("firebase-functions");
const admin = require("firebase-admin");
if (admin.apps.length === 0) {
admin.initializeApp({
credential: admin.credential.applicationDefault(),
});
}
exports.membersByPhoneNumber = functions.https.onCall((data, context) => {
return new Promise((resolve, reject) => {
if (!data || !data.allPhoneNumbers.length) return resolve([]);
const phoneNumbers = data.allPhoneNumbers;
// TODO: different scope? move vars for future use
const db = admin.firestore();
const collectionRef = db.collection("User");
let batches = [];
// because of wrong eslint parsing (dirty)
batches = [];
while (phoneNumbers.length) {
// firestore limits batches to 10
const batch = phoneNumbers.splice(0, 10);
// add the batch request to to a queue
batches.push(
new Promise((response) => {
collectionRef.where("Phone", "in", [...batch]).get()
.then((results) =>
response(results.docs.map(function(result) {
return result.data().Phone;
} )));
})
);
}
// response / return to client
Promise.all(batches).then(function(content) {
// console.log("content.flat()");
// console.log(content.flat());
return resolve(content.flat());
});
});
});
注意:这是我们的第一个callable/cloud功能..欢迎提出更改建议。
我目前正在使用 Firebase 开发应用程序。
我的 Firestore 数据库如下所示:
用户通过 Firebase 身份验证程序后,我将创建一个包含字段“Phone:”的用户文档,其中包含他的 phone 号码。基本上,所有要使用该应用程序的人都会在数据库中列出。
这是我的挑战:
我正在使用插件 easy_contact_picker 将用户设备的所有联系人存储到列表中。
我如何知道用户联系人是否正在使用该应用程序或他们是否在数据库中列出?
我的目标是创建一个显示我所有联系人的联系人列表小部件。但那些正在使用该应用程序或在数据库中列出的联系人应特别突出或标记。
如果我们考虑数据库中列出了数百万用户(以最小化计算能力),那么实现这一点的最佳方式是什么?
有人有想法吗?
非常感谢
首先尽量避免让每个人都可以阅读所有用户。这是大多数人在处理此类问题时所做的事情。这样做是因为如果您不授予阅读所有用户的权限,则对所有用户的查询将无法工作。
出于安全原因,我会将检查用户是否存在的逻辑移动到可调用函数(不是 http 函数!)中。这样您就可以在您的应用程序内部调用它并检查数组中的单个用户或多个用户。这将取决于您的前端如何处理它。
非常重要,而且将以完全相同的格式存储所有 phone 数字。这样你就可以查询它们。无论有多少用户,您总能像这里一样找到特定用户:
var citiesRef = db.collection("users");
var query = citiesRef.where("Phone", "==", "+4912345679");
数字必须完全相同,不能有任何空格 -
字符,+49 或 0049 也必须相同。
您可以创建两个可调用函数。一个检查您的应用程序中是否存在单个用户,另一个检查您发送一个 phone 数字数组并返回一个数组。云函数可以使用 Promise.all
并行执行此类查询,因此您可以获得非常快的响应。
我正在使用类似的方法将我的应用程序中的用户添加为特定组的管理员,您只需在其中输入用户的电子邮件,如果他在应用程序中,他将被添加。我不是他在电子邮件中收到加入应用程序的邀请。
在 Tarik 的回答的帮助下,Ayrix 和我想出了以下解决方案。
重要提示:阅读 Tarik 的回答以获取更多信息。
客户: callable_compare_contacts.dart
import 'package:cloud_functions/cloud_functions.dart';
Future<List<Object>> getMembersByPhoneNumber(List<String> allPhoneNumbers) async {
HttpsCallable callable = FirebaseFunctions.instance.httpsCallable('membersByPhoneNumber');
final results = await callable.call(<String, dynamic>{'allPhoneNumbers': allPhoneNumbers});
return results.data;
}
服务器: index.js
const functions = require("firebase-functions");
const admin = require("firebase-admin");
if (admin.apps.length === 0) {
admin.initializeApp({
credential: admin.credential.applicationDefault(),
});
}
exports.membersByPhoneNumber = functions.https.onCall((data, context) => {
return new Promise((resolve, reject) => {
if (!data || !data.allPhoneNumbers.length) return resolve([]);
const phoneNumbers = data.allPhoneNumbers;
// TODO: different scope? move vars for future use
const db = admin.firestore();
const collectionRef = db.collection("User");
let batches = [];
// because of wrong eslint parsing (dirty)
batches = [];
while (phoneNumbers.length) {
// firestore limits batches to 10
const batch = phoneNumbers.splice(0, 10);
// add the batch request to to a queue
batches.push(
new Promise((response) => {
collectionRef.where("Phone", "in", [...batch]).get()
.then((results) =>
response(results.docs.map(function(result) {
return result.data().Phone;
} )));
})
);
}
// response / return to client
Promise.all(batches).then(function(content) {
// console.log("content.flat()");
// console.log(content.flat());
return resolve(content.flat());
});
});
});
注意:这是我们的第一个callable/cloud功能..欢迎提出更改建议。