Resolving an Error 400 with Firebase/Firestore and VueJS - firebase

I am attempting to write an ordering app using Google Firebase as the database to store everything. I attempted to test the connection but keep getting GET and POST HTTP 400 errors when I submit test data.
I have installed v8.0.0 via NPM. My firebase.js file is as follows:
import firebase from 'firebase/app'
import 'firebase/firestore'
import { firebaseConfig } from '#/firebaseConfig';
firebase.initializeApp(firebaseConfig);
const db = firebase.firestore();
export const dbMenuRef = db.collection("menu");
Fire security purposes I keep the object Google generates for configuration containing the keys and such in a separate file. I even tried putting the object in the firebase.js file and still got these errors.
The data is structured as follows:
newOrder: {
customerName: 'John Doe',
customerPhone: '1-800-DRUIDIA',
items:[{
itemUPC: '1234567890',
itemDesc: 'A generic item',
itemDist: 'The one we always use'
}, {
itemUPC: '0987654321',
itemDesc: 'Another Generic Item',
itemDist: 'The other one we use'
}]
}
Data is two-way bound to a form. This is working properly and I have the newOrder object displayed in the component. This is working just fine as the JSON looks like above.
The following VueJS method is triggered by clicking a "Submit Order" button.
addOrder() {
dbMenuRef.add(this.newOrder)
}
Edit: I am using Firefox Developer Edition latest version.
Second Edit: This apparently works in Chrome, but not Firefox DE.

It looks like you are passing array as a value to items key. If you use dbMenuRef.add, you might want to add as sub-collections. Instead, you can use .set if you want to have the entire document added (please refer the documentation here. Can you try:
addOrder() {
dbMenuRef
.doc(this.orderID)
.set(this.newOrder)
}

Related

Nuxt/algolia's AlgoliaDocSearch component does not return elements

I am using the #nuxt/algolia package and using the component. I've also setup the runtime config as shown below. However queries do not return anything (they say, "no results for "). When I look at the chrome network tab I can see the queries are coming back as status 200 and the correct index name is being called, but when I click on the failure and the web page opens there is an error {"message":"indexName is not valid","status":400}.
The weird thing here is that I have custom js code that uses the same env variables including the indexName and that code works. What am I doing wrong?
algolia: {
apiKey: process.env.ALGOLIA_SEARCH_API_KEY,
applicationId: process.env.ALGOLIA_APPLICATION_ID,
docSearch: {
indexName: process.env.ALGOLIA_INDEX
}
},
<template>
<AlgoliaDocSearch />
</template>
I have other js custom code that is able to both query and update indexes with the same env variables.

What is the difference between axios and useFetch (nuxt 3)?

I'm slowly starting to migrate from nuxt 2 to nuxt 3.
Previously I used to use axios.
In Nuxt3, it is recommended to use useFetch
However the behavior is quite weird with useFetch. Calls are not made systematically.
For example in this piece of code :
async mounted() {
const store = useAuth();
let response = await axios.get('http://dev.test.fr/api/secured/admin', {headers : store.authHeader() });
this.sensibleInformation = response.data;
},
With Axios, every time I open this page, the call is made and the sensibleInformation is up to date.
With useFetch, the syntax is similar
async mounted() {
const store = useAuth();
let response = await useFetch('http://dev.malt.fr/api/secured/admin' , {method : 'get', headers : store.authHeader() });
this.sensibleInformation = response.data;
},
But the call to the server is done... sometimes. So, the sensibleInformation is most of the time empty. And I don't find any explanation in the documentation.
Maybe there is something I miss here.
I'm using nuxt 3.0.0-rc.6
As it is explained in nuxtJS3 useFetch
useFetch is a wrapper for $fetch(come from here ohmyfetch)
you don't need to import this lib it is include in vuejs3 and lastly axios was not compatible with vuejs3 explained here why use $fetch
what is really great is that body is automatically parsed in JSON, so no need to parse or stringify anything. Also header for content type is automatically added.
So no need to import any library, automatic parsing, automatic header detected etc...
Not sure about this one, but I think the "useFetch" helper is designed to be used with the Vue composition API, so :
within the "setup" function
directly in your script tag if you're using the "<script setup>" synthax
The issue you are dealing with maybe due to the fact that you're using "useFetch" within the "mounted" hook of Vue.js options API.
But once again, not sure about this one :)
The major difference between useFetch and Axios is that useFetch is a wrapper around useAsyncData (and native $fetch) and so works with both SSR and Static modes of Nuxt.
If using it in the onMounted hook you will probably get more expected results if you set the server option to false so it runs only in the client (more like how Axios runs in the mounted hook). I have predominantly used it in <script setup> for SSR set ups.
More info here: https://v3.nuxtjs.org/api/composables/use-fetch

Linking images from Firebase Storage to Firestore document and displaying them in React Native

Background
I'm trying to upload images to firebase storage manually (using the upload file button in the web page), however I have no clue how to later link them to a firestore document. What I have come up with (I'm unsure if it works) is copying the url for the image in the storage bucket and adding it to a string type field in the document called profilePicture. The reason I'm unable to get this to work is that I'm really new to React Native and I don't know how to properly require the images other than typing in the specific local route. Mind you also, the way I'm requiring user data such as a profile name is after logging in with email/password auth I pass the data as a param to react navigation and require it as extraData.
What I have tried
Once I've copied the image url and pasted it in the firestore document I'm doing this:
const profilePicture = props.extraData.profilePicture;
<Image source={require({profilePicture})}/>
I have also tried using backticks but that isn't working either. The error message I'm getting is:
TransformError src\screens\Profile\ProfileScreen.js: src\screens\Profile\ProfileScreen.js:Invalid call at line 27: require({
profilePicture: profilePicture
})
Note: this is an expo managed project.
Question
Is the problem in the code or in the way I'm linking both images? Maybe both? Should I require the document rather than relying on the data passed previously?
Thanks a lot in advance!
Edit 1:
I'm trying to get all info from the current user signed in, after a little research I've come to know about requiring images in this manner:
const ref = firebase.storage().ref('path/to/image.jpg');
const url = await ref.getDownloadURL();
and then I'd require the image as in <Image source={{uri: url}}/>
I get that this could be useful for something static, but I don't get how to update the ref for every single different user.
Edit 2:
Tried using the method mentioned in Edit 1, just to see what would happen, however It doesn't seem to work, the image just does not show up.
Maybe because my component is a function component rather than a class component (?
I understand that your goal is to generate, for each image that is uploaded to Cloud Storage, a Firestore document which contains a download URL.
If this is correct, one way is to use a Cloud Function that is triggered each time a new file is added to Cloud Storage. The following Cloud Function code does exactly that. You may adapt it to your exact requirements.
exports.generateFileURL = functions.storage.object().onFinalize(async object => {
try {
const bucket = admin.storage().bucket(object.bucket);
const file = bucket.file(object.name);
// You can check that the file is an image
const signedURLconfig = { action: 'read', expires: '08-12-2025' }; // Adapt as follows
const signedURLArray = await file.getSignedUrl(signedURLconfig);
const url = signedURLArray[0];
await admin.firestore().collection('profilePictures').add({ fileName: object.name, signedURL: url }) // Adapt the fields list as desired
return null;
} catch (error) {
console.log(error);
return null;
}
});
More info on the getSignedUrl() method of the Admin SDK here.
Also note that you could assign the Firestore document ID yourself, instead of having Firestore generating it as shown in the above code (with the add() method). For example, you can add to the image metadata the uid of the user and, in the Cloud Function,get this value and use this value as the Document ID.
Another possibility is to name the profile image with the user's uid.

Firebase Full-Text Search using Algolia

I configured different firebase functions by following this
. Now in this, there is firebase full-text search. I tried to follow it but it seems to be incomplete. I have searched and somehow got success in deploying. But it is still not creating index in Algolia. Can someone tell me the steps to correctly perform this?
I created the blog-posts and search nodes in my firebase project but problem is still there.
CODE:
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
// Authenticate to Algolia Database.
// TODO: Make sure you configure the `algolia.app_id` and `algolia.api_key` Google Cloud environment variables.
const algoliasearch = require('algoliasearch');
const client = algoliasearch(functions.config().algolia.app_id, functions.config().algolia.api_key);
// Name fo the algolia index for Blog posts content.
const ALGOLIA_POSTS_INDEX_NAME = 'blogposts';
// Updates the search index when new blog entries are created or updated.
exports.indexentry = functions.database.ref('/blog-posts/{blogid}/text').onWrite(event => {
const index = client.initIndex(ALGOLIA_POSTS_INDEX_NAME);
const firebaseObject = {
text: event.data.val(),
objectID: event.params.blogid
};
return index.saveObject(firebaseObject).then(
() => event.data.adminRef.parent.child('last_index_timestamp').set(
Date.parse(event.timestamp)));
});
// Starts a search query whenever a query is requested (by adding one to the `/search/queries`
// element. Search results are then written under `/search/results`.
exports.searchentry = functions.database.ref('/search/queries/{queryid}').onWrite(event => {
const index = client.initIndex(ALGOLIA_POSTS_INDEX_NAME);
const query = event.data.val().query;
const key = event.data.key;
return index.search(query).then(content => {
const updates = {
'/search/last_query_timestamp': Date.parse(event.timestamp)
};
updates[`/search/results/${key}`] = content;
return admin.database().ref().update(updates);
});
});
SEE IMAGE OF FIREBASE NODE
Open Image
Your help will be appreciated. Thanks
So I used the sample code provided here and placed it into a Firebase cloud function. Writing to '/blog-posts/{blogid}/text' inside the database should index whatever value is under text to Algolia.
There are a few things that might be going wrong here:
Check that your function is correctly placed into Firebase. You can do this from the console by clicking functions on the left side. You should see two functions named indexentry and searchentry. If you do not see those functions then you haven't correctly pushed your code to the Firebase cloud.
If you code is in Firebase cloud then I recommend adding console.log("write on blog-posts fired"); to your searchentry function. Then write some more data to your database under '/blog-posts/{blogid}/text'. You can check the function log in the Firebase console. I have noticed a slight delay in log records displaying some times, so be patient if you don't see it right away. I'd write a few pieces of data to '/blog-posts/{blogid}/text' then after a couple minutes I'd check the log. If the log has "write on blog-posts fired" in it then you know the function is being activated when you write to the database.
If all the above is operating correctly and you still don't have any data in Algolia then make sure you set your API keys. You can do this using the code firebase functions:config:set algolia.app_id="myAlgoliaAppId" algolia.api_key="myAlgoliaApiKey". You run this command in a terminal window inside the directory where you have your Firebase cloud functions. You can get you API keys by signing into your account. Remember not to share your API key with anyone.

Meteor not publishing all user fields with autopublish package

I have not removed autopublish nor insecure package but when I run Meteor.user() it shows the services. Facebook object but not the services.google object (nor the services.password but I don't need that one).
The Google and Facebook objects are definitely both in the database, why would it only show one? How would you go about troubleshooting? I thought all fields were puckishness when autupub was on.
First, make sure "accounts-base", "accounts-facebook" and "accounts-google" are listed in your ".meteor/packages" file. Everything indicates that you don't have the "accounts-google" package added to that file.
The "accounts-base" package, which publishes "Meteor.users", overwrites the default autopublish functionality (https://github.com/meteor/meteor/blob/devel/packages/accounts-base/accounts_common.js#L82).
To see which fields get auto published refer to the source code at accounts_server.js, starts at: https://github.com/meteor/meteor/blob/devel/packages/accounts-base/accounts_server.js#L683
You'll see the following (read the comment):
// If autopublish is on, publish these user fields. Login service
// packages (eg accounts-google) add to these by calling
// Accounts.addAutopublishFields Notably, this isn't implemented with
// multiple publishes since DDP only merges only across top-level
// fields, not subfields (such as 'services.facebook.accessToken')
var autopublishFields = {
loggedInUser: ['profile', 'username', 'emails'],
otherUsers: ['profile', 'username']
};
Which means "Accounts.addAutopublishFields" method will be called by the "accounts-google", "accounts-facebook", etc packages to add fields to that publication.
Now for example if you look at the "accounts-google" package, in the "google.js" file, it has the following:
Accounts.addAutopublishFields({
forLoggedInUser: _.map(
// publish access token since it can be used from the client (if
// transmitted over ssl or on
// localhost). https://developers.google.com/accounts/docs/OAuth2UserAgent
// refresh token probably shouldn't be sent down.
Google.whitelistedFields.concat(['accessToken', 'expiresAt']), // don't publish refresh token
function (subfield) { return 'services.google.' + subfield; }),
forOtherUsers: _.map(
// even with autopublish, no legitimate web app should be
// publishing all users' emails
_.without(Google.whitelistedFields, 'email', 'verified_email'),
function (subfield) { return 'services.google.' + subfield; })
});
Which means that if you have the "accounts-google" packaged enabled, it publishes the following fields to "Meteor.users":
When logged in: 'profile', 'username', 'emails' and all "service.google" fields except 'accessToken', 'expiresAt'
When logged off: 'profile', 'username' and all "service.google" fields except 'email', 'verified_email'
Same thing for the "accounts-facebook" package.

Resources