I'm trying to write a Firebase Cloud Function to get an audio file from an API and save it to Firebase Storage. I'm getting this error:
Firebase Storage: User does not have permission to access 'Audio/English/United_States-OED-0/winter.mp3'. (storage/unauthorized)
I'm getting the same error using the emulator and the cloud. No file is written in Storage. The log Uploaded a string!'
doesn't appear.
I have a Firebase IAM service account. I know how to import it into a CommonJS module (require
) but my functions are in an ES module (import
). How do I import my service account? This didn't work because assert
only works in Node 17, when Firebase Functions uses Node 16.
import serviceAccount from "./my-awesome-project-firebase-adminsdk-12345.json" assert { type: "json" };
Here's my cloud function:
import { initializeApp } from "firebase/app";
import * as functions from "firebase-functions";
import { getStorage, ref, uploadString, connectStorageEmulator } from "firebase/storage";
const firebaseConfig = {
apiKey: ...,
authDomain: ...,
databaseURL: ...,
projectId: ...,
storageBucket: "my-awesome-project.appspot.com",
appId: "..."
};
const app = initializeApp(firebaseConfig);
import got from 'got';
export const Oxford_T2S = functions.firestore.document('Users/{userID}/English/OED_T2S_Request').onUpdate((change, context) => {
const storage = getStorage(app);
connectStorageEmulator(storage, "localhost", 9199); // comment out to use cloud
const audioEnglishOEDWinterRef = ref(storage, 'Audio/English/United_States-OED-0/winter.mp3');
async function getOED() {
try {
let file = await got('https://audio.oxforddictionaries.com/en/mp3/winter__us_2.mp3');
uploadString(audioEnglishOEDWinterRef, file).then((snapshot) => {
console.log('Uploaded a string!');
});
} catch (error) {
console.error(error);
}
}
return getOED()
});
Here are my cloud rules:
service firebase.storage {
match /b/{bucket}/o {
// anything using request.auth.token relies on the userLogin cloud function.
match /Audio/{shortLangA}/{file=**} {
// allow writing of audio files if the user is trusted or a teacher of the language, apply recursively
allow write: if (request.auth.token.trusted || shortLangA in request.auth.token.teaches);
}
match /Users/{file=**} {
// allow writing of pronunciation tests
// this rule is insecure
// this rule needs to be improved by allowing users to only write to their own folders
allow read, write: if true;
}
match /{allPaths=**} {
// Only authenticated users can read from the bucket
allow read: if request.auth != null;
}
}
}
I tried spinning up my Angular project and logging in but that didn't help.
Here are my emulator rules. These are the default rules created by firebase init functions
:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if false;
}
}
}
I changed false
to true
but that didn't help.
Documentation on got
is here. That line isn't throwing errors.