Admin SDK + Vuejs ListAllUsers? - firebase

I have read the documentation about listing all users via admin SDK but still struggling to show users in my vue component...
the code in the documentation is:
function listAllUsers(nextPageToken) {
// List batch of users, 1000 at a time.
admin.auth().listUsers(1000, nextPageToken)
.then(function(listUsersResult) {
listUsersResult.users.forEach(function(userRecord) {
console.log('user', userRecord.toJSON());
});
if (listUsersResult.pageToken) {
// List next batch of users.
listAllUsers(listUsersResult.pageToken);
}
})
.catch(function(error) {
console.log('Error listing users:', error);
});
});
// Start listing users from the beginning, 1000 at a time.
listAllUsers();
in my component, I want to create an array that will contain all users and display them,.. The question is,.. How would I do that? is it by an axios request? and what are the steps?

As explained in the documentation "the Admin SDK supports Node.js, Java, and Python." This means that you cannot use the code in your question directly in a Vue.js component. You need to execute this code in a backend and call this backend from your Vue.js component.
One of the standard solution would be to create a Callable Cloud Function that executes this code and returns the list of users as an array. The documentation explains how to implement such a function and how to call it from your vue.js application (See here).
You could also use a "standard" HTTPS Cloud Function and call it via Axios, but using a Callable Cloud Functions brings some extra advantages as explained in the doc ("Firebase Authentication and FCM tokensare automatically included in requests, the functions.https.onCall trigger automatically deserializes the request body and validates auth tokens.", etc...).

Related

How to restrict a Google Cloud function to be invoked only from the Google Cloud Console?

I have a Firebase function to do some data processing, and I only want to invoke it through Google Cloud Console manually.
Just a simple function like this (using node.js):
import * as functions from 'firebase-functions'
// // Start writing Firebase Functions
// // https://firebase.google.com/docs/functions/typescript
//
export const test = functions.https.onRequest(async (req, res) => {
res.send({
query: req.query,
body: req.body,
})
})
The way I did it is to deploy the function via the firebase-cli then remove the Cloud Function Invoker role in the permission tab from GUI.
It seems to work.
But I noticed one thing, when I send the request with Postman
when you send a GET, the error is 400,
But for any request that's not a GET, you get a proper 403
My questions are:
why GET is 400 while the others are 403?
am i doing it right in terms of my requirement?
what's the correct way of doing it?
does the function get invoked while sending a request like POST?

Nuxt SPA dynamic routes based on Firebase Firestore data

So I want to have a nuxt site hosted on Netlify where there's a child route whos slug is a firebase firestore document id.
Example:
https://www.example.com/users/steve
(where "steve" is the documentid)
So when the route is hit I would need to query firebase to see if it exists, and if not I would have to return a 404. Is this even possible? I can do it easy in .net or php, but I'm very unsure of a SPA.
Specifically what should I be looking for in the docs, if I can do this?
One solution is to implement an HTTPS Cloud Function that you would call like a REST API, sending an HTTP GET request to the functions endpoint.
As explained in the doc "Used as arguments for onRequest(), the Request object gives you access to the properties of the HTTP request sent by the client".
So you Cloud Function would look like:
exports.getUser = functions.https.onRequest((req, res) => {
// get the value of the user by parsing the url
const baseUrl = req.baseUrl;
//Extract the user from baseUrl
const user = ....
//query the Firestore database
admin.firestore().collection('users').doc(user).get()
.then(doc => {
if (doc.exists) {
res.status(200).end();
} else {
res.status(404).end();
}
});
See the get started page and the video series for more info on Cloud Functions.
Note that you can connect an HTTP function to Firebase Hosting, in such a way that "requests on your Firebase Hosting site can be proxied to specific HTTP functions".

Firebase cloud function to use sendgrid for sending emails when a contact form gets submitted to firestore

I want my firebase backend to send an email to me when a document is created in a firestore collection based on a form submission in my vue app..
I found sendgrid to be the easiest to get the job done, the example mentioned in the package page suggests that I store the API key in an Environment variable.
Since this will run from a cloud function, I used the following command firebase functions:config:set sendGrid.key="THE API GOES HERE" as mentioned in Firebase docs here
cloud function
I initialized the firebase cloud functions locally, then I called the admin module so i can listen to onCreate() when a document is created in firestore,
I used sendGrid inside the callback function of onCreate()..
I tested the code and checked the functions logs in my firebase project and it gets invoked and finished successfully with a status ok, which means that everything should be working fine.
here is my index.js code inside the /functions folder in my project root
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
// sendGrid
const sgMail = require('#sendgrid/mail');
// the cloud function
exports.formSubmitted = functions.firestore.document('message/{messageId}').onCreate(doc => {
// referencing the form data
const formData = doc.data();
// the following should be logged in the function logs in my firebase project
console.log(formData);
// retrieving the environment variable
sgMail.setApiKey(functions.config().sendgrid.key);
// the message to be sent
const msg = {
to: 'MY-EMAIL#gmail.com',
from: formData.email,
subject: 'new user submitted our contact form',
text: formData.message,
html: '<h3> test email from sendGrid </h3>'
}
return sgMail.send(msg);
})
result:
everything worked fine except I didn't receive the email.
If further code/explanation is needed, please leave a comment below.
any help or hints is highly appreciated, thanks in advance.

How to run ElasticSearch on user's devices AND keep ElasticSearch server safe?

Writing a mobile app with Firebase being my backend, also using ES to power my search. I'm completely new to ES.
Suppose each user can publish articles, each of which contains some number of tags, which denotes what this article is about, kind of like questions asked here. Users can search for articles, with tags, and articles containing that tag will be displayed. I manage to do that with Cloud Function, so, the Cloud Function basically looks like this:
exports.articleSearch = functions.https.onRequest((req, res) => {
const { tag } = req.query;
const ElasticSearchConfig = {
uri: '..<my elastic cloud url>/articles/article/_search...',
method: 'GET',
body: ...,
json: true,
auth: {
username: '...<my elastic cloud username>...',
password: '...<my elastic cloud password>...'
}
};
// If succeeds, send results back to user, if not, send error back
request(ElasticSearchConfig).then((results) => ...)
.catch((error) => ...);
});
This works, however, it's a bit slow, because I'm not running ElasticSearch on user's devices, instead, through a cloud function. But if I do run the above code on user's devices, you noticed auth property of ElasticSearchConfig object, I'm basically giving everybody permissions to access and manipulate my ES server. How can I run the above code on user's devices and at the same time, prevent them from reading or writing anything without proper permission?
There's no secure way to do what your asking. Even if it was possible, you don't want that kind of processing client side draining the battery, especially on mobile. Your slow response from cloud functions may be caused from the function entering a timeout state, meaning it hasn't been called in a while.

meteor-shopify authenticator getPermanentAccessToken with code

I'm using the froatsnook:shopify atmosphere package to create an embedded public app on Shopify. I currently have a couple issues:
1) Getting the access token from the "code" query parameter after a user authenticates. As it mentions in the docs here, I'm supposed to use authenticator.getPermanentAccessToken(code) but what I don't understand is how to get call authenticator if the "code" parameter appears on the callback route (at that point, the authenticator I instantiated on the client pre-auth route is out of scope).
2) The "oAuth" function callback is never called for some reason, even when assigning it to Shopify.onAuth on the server.
3) The difference between post_auth_uri and redirect_uri ?
// I call this during 'onBeforeAction' for iron-router
function beforeAuth (query) {
// is this necessary..?
console.assert(Meteor.isClient);
// get shop name like 'myshop' from 'myshop.shopify.com';
const shop = query.shop.substring(0, query.shop.indexOf('.'));
// use api_key stored in settings
var api_key = Meteor.settings.public.shopify.api_key;
// Prepare to authenticate
var authenticator = new Shopify.PublicAppOAuthAuthenticator({
shop: shop,
api_key: api_key,
keyset: 'default',
embedded_app_sdk: true,
redirect_uri: 'https://45a04f23.ngrok.com/testContent',
//post_auth_uri: ???
// This is doesn't seem to be getting
// called after clicking through the OAuth dialog
onAuth: function(access_token) {
ShopifyCredentials.insert({
shop: shop,
api_key: api_key,
access_token: access_token
});
}
});
// Should i use something different with iron-router?
location.href = authenticator.auth_uri;
// how do i get code in this scope???
// authenticator.getPermanentAccessToken(code);
}
There are a few issues with the way you are trying to set up the authenticator, although it's not really your fault because the way Scenario 3 works in the docs is not an 'out of the box' solution and requires a bunch of custom code, including your own handler (I can provide a gist if you REALLY want to build your own handler, but I suggest using the new server-side onAuth callback instead)
1. Specifying a redirect_uri overrides the package's default redirect_uri handler which is Meteor.absoluteUrl("/__shopify-auth").
So instead, completely remove redirect_uri and put your testContent url in post_auth_uri instead.
2. ShopifyCredentials does not exist in this package. If you want to use it that way, make sure you actually have defined a collection called 'ShopifyCredentials' and insert the record from the server, not the client. Note that you will still need to add a keyset on the server for the API methods to work. If you are using user accounts and would like to permanently store credentials, I suggest saving the credentials to the database and adding the keyset via a server-side onAuth callback.
3. authenticator.getPermanentAccessToken(code) isn't useful unless you are using your own handler. Instead, you can just get access_token from the onAuth callback.
Also keep in mind that if you ever need to reauthenticate from inside the embedded app, you need to use window.top.location.href to break out of the iframe.
If you want a complete, working boilerplate example with user accounts see my gist here:
Authentication with Accounts and Persistent Keysets
If you aren't using accounts, you can use this gist instead, but please note that you really need to come up with some way to check that the current client has permission to request the keyset for a given shop before going to production:
Authentication with Persistent Keysets

Resources