Вот настоящий головокружитель. У меня есть облачная функция, которая использует https.onCall (). Этот вызов функции вызывается из защищенной паролем области в моем приложении Android (я использую Firestore в качестве сервера). Чтобы получить доступ к этой области, я заставляю пользователя повторно вводить свой пароль, который затем вызывает FirebaseAuth.getInstance (). GetCurrentUser (). Reauthenticate ().
Я выполнил код, который вызывает облачную функцию https.onCall () без повторной аутентификации, и функция сохраняет учетные данные пользователя для аутентификации, поэтому я сузил его до некоторой степени при повторной аутентификации. Я что-то пропустил? Нужно ли что-то делать, чтобы сообщить облачной функции об обновлении аутентификации?
Сообщение об ошибке, которое я получал в журналах функций:
Msgstr "Ошибка типа: невозможно прочитать свойство 'uid' неопознанного объекта". В частности, это происходило, когда я пытался получить uid аутентифицированного пользователя с помощью следующего:
const adminUID = context.auth.uid;
Предполагалось, что из-за того, что я не получил вышеуказанную ошибку, это потому, что не было аутентифицированных данных, поступающих через контекст.
Чтобы лучше понять, что происходит, вот мой поток / процесс:
Пользователь выбирает «Аккаунт» из меню настроек. Это запускает dialogFragment, который запрашивает пароль пользователя:
Код кнопки в диалоговом фрагменте:
loginButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view) {
//execute the loginReAuth method
authenticateSession.loginAdminReAuth(adminEmailAddress, passwordField);
}
});
После выбора кнопки loginButton и ввода пароля пользователем мы передаем данные в метод повторной аутентификации:
Повторно подтвердить подлинность кода:
public void loginAdminReAuth(final String email, TextView passwordText) {
user = FirebaseAuth.getInstance().getCurrentUser();
String password = passwordText.getText().toString();
AuthCredential credential = EmailAuthProvider.getCredential(email, password);
user.reauthenticate(credential)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Intent intent = new Intent(context, AccountSettingsActivity.class);
context.startActivity(intent);
} else {
// If sign in fails, display a message to the user.
Log.w(TAG, "re-authenticate:failure", task.getException());
Toast.makeText(MyApplication.getContext(), task.getException().getMessage(),
Toast.LENGTH_SHORT).show();
}
}
});
}
Когда повторная аутентификация успешна, мы запускаем намерение и переносим их в AccountSettingsActivity. Внутри этого действия у меня есть метод: deleteAccount (), который запускается кнопкой, щелкает в alertDialog, подтверждающем действие.
Вот кнопка Click, которая вызывает метод:
@Override
public void onDialogOKPressed(DialogFragment dialog) {
dialog.dismiss();
if (buttonSelected.equals("accountUpdateButton")) {
//update code here.
}
else if (buttonSelected.equals("accountDeleteButton")) {
deleteAccount(admin);
}
}
Вот метод deleteAccount (), который делает запрос облачной функции:
метод, который вызывает облачную функцию:
private Task<String> deleteAccount(Admin selectedAdmin) {
Gson gson = new Gson();
String selectedAdminJson;
selectedAdminJson = gson.toJson(selectedAdmin);
Map<String, Object> data = new HashMap<>();
data.put("selectedAdminJson", selectedAdminJson);
return mFunctions
.getHttpsCallable("deleteAccount")
.call(data)
.continueWith(new Continuation<HttpsCallableResult, String>() {
@Override
public String then(@NonNull Task<HttpsCallableResult> task) throws Exception {
// This continuation runs on either success or failure, but if the task
// has failed then getResult() will throw an Exception which will be
// propagated down.
Log.d(TAG, "results from deleteAccount: " + task.getResult().getData().toString());
String result = (String) task.getResult().getData();
return result;
}
});
}
Наконец, вот код облачного пожарного хранилища, который выполняет запрос.
Облачная функция https.onCall ():
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
import * as functions from 'firebase-functions';
// The Firebase Admin SDK to access the Firebase Realtime Database.
import * as admin from 'firebase-admin'
export = module.exports = functions.https
.onCall(async (data, context) => {
//selectedAdminJson received from app client and converted to admin object class
const selectedAdminJson = data.selectedAdminJson;
const adminUID = context.auth.uid;
//Error checking
// Checking attribute.
if (!(typeof selectedAdminJson === 'string') || selectedAdminJson.length === 0) {
// Throwing an HttpsError so that the client gets the error details.
throw new functions.https.HttpsError('invalid-argument', 'The function must be called with ' +
'one arguments "JSON object" containing selectedAdmin to add.');
}
// Checking that the user is authenticated OR if the calling adminID doesn't match the data received
if (!context.auth) {
// Throwing an HttpsError so that the client gets the error details.
throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' +
'while authenticated.');
}
try {
//METHODS EXECUTED HERE
} catch (error) {
console.error("Error removing adminUserGroup data: ", error);
}
// Returning result to the client.
return {
selectedAdminJson: "selectedAdminJson received and processing."
};
});
Еще один кусок. Это часть моего index.ts:
import * as admin from 'firebase-admin'
admin.initializeApp();
if (!process.env.FUNCTION_NAME || process.env.FUNCTION_NAME === 'deleteAccount') {
exports.deleteAccount = require('./deleteAccount');
}