When the user uploads a photo to storage
This means that you need to use a Cloud Function that is triggered by a Cloud Storage event and not a CF triggered by the Authentication Service event (BTW functions.auth.getUser()
does not exist, see the doc).
The following should do the trick (untested).
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp()
exports.updateUrl = functions.storage.object().onFinalize(async (object) => {
try {
const newPhotoStorageFile = admin.storage().bucket(object.bucket).file(object.name);
const signedURLconfig = { action: 'read', expires: '01-01-2030' };
const newPhotoURLArray = await newPhotoStorageFile.getSignedUrl(signedURLconfig);
const newPhotoURL = newPhotoURLArray[0];
const newPhotoStoragePath = object.name;
const userId = newPhotoStoragePath.split("/")[1].split(".")[0]; // Double check this simple extraction code is valid for all your cases.
await admin.auth().updateUser(userId, { photoUrl: newPhotoURL });
return true;
} catch (error) {
console.log(error);
return null;
}
});
At this stage if you run this Cloud Function you'll get the following error: Error: Permission 'iam.serviceAccounts.signBlob' denied on resource (or it may not exist)
.
Assigning, via the Google Cloud console, this IAM permission to the App Engine default service account, PROJECT_ID @appspot.gserviceaccount.com
would solve the problem.
HOWEVER, you would face another problem: The SignedURL has a short life duration due the problem described in this SO answer. So you need to use the Google Cloud Storage npm module and initialize it with a service account json file.
const {Storage} = require('@google-cloud/storage');
const storage = new Storage({keyFilename: "key.json"});
const newPhotoStorageFile = storage.bucket(object.bucket).file(object.name);