Firebase admin auth list users does not return all users in the project - firebase-admin

the userList result contains only one userRecord while all the users are around 8
corsHandler(request, response, () => {
admin.auth().listUsers(10, 'token')
.then((UserListResult) => {
if (UserListResult.pageToken) { console.log('is found') }
response.status(200).send(UserListResult)
})
.catch(error => response.send(error))
})

Finally, I resolved this.
It seems that if the pageToken is a null or an invalid string, it returns just one record (based on a couple of tests, last user record)
I changed my code as below and it is working
import * as express from 'express'
import * as admin from 'firebase-admin'
import { validate } from '../middleware/auth.middleware';
const router = express.Router()
/** List users */
router.get('/', async (req, res) => {
let { limit, page } = req.query
limit = parseInt(limit) || 25;
page = page === 'null' ? null : page;
try {
// Adding a conditional operator here, one with pageToken & other with just limit
const users: admin.auth.ListUsersResult = page ? await admin.auth().listUsers(limit, page || null) : await admin.auth().listUsers(limit);
const nextPageToken: string = users.pageToken;
res.status(200).json({ message: 'Success', users: [...users.users], nextPageToken }).end();
} catch (err) {
console.error(err);
res.status(500).json({ message: 'Internal Server Error' }).end();
}
});
export { router }

Related

how to catch error of an asyn function call

I don't succeed catching the error that a async function returns. Using Vuejs 3 with a pinia store, althought I don't think that this is specific to vue or pinia.
In a pinia store I have this function:
const getAccount = async(id, month, year) => {
try {
getData.defaults.headers.common['__authorization__'] = UserStore.jwt
const response = await getData.get(`/use/b/comptes/${id}/${month}/${year}`)
if (response.status === 200) {
// update store state and:
return true
}
return false
} catch (error) {
// => this gets correctly executed when the server responds with 409
// console.error(`erreur catch : ${error.response.data.error}`)
return error.response.data
}
}
I'm calling this function from a component, like so:
watchEffect(() => {
if (route.name === 'comptes') {
getAccount( compte.value.id, route.params.month, route.params.year )
.then(result => { console.log('result', result.error) })
.catch(err => {
// this never gets executed, including when server returns a 409
console.log('err', err)
})
}
})
In other words: in the function call, only the then block gets executed, not the catch.
How do I catch the error of the first function?

ParseServer object not found

Parse.Query in cloud code cant find object
Running this code cloud function as a user who can reject or accept Invites. The code gets the invite (works) and checks for the given deckId, where the user should be added as a collaborator.
But for some reason i can't explain the Query for the Deck always returns:
https://pastebin.com/XjLjvzXZ
I have checked:
the docs for syntax -> should be fine
the Invite object exists and has a deckId
The Deck Objects exist and the deckId and Deck's objectId are matching
Parse.Cloud.define("inviteAction", async (request) =>
{
const user = request.user;
const inviteId = request.params.invite;
const action = request.params.actiom;
let inviteQuery = new Parse.Query("Invite");
const invite = await inviteQuery.get(inviteId, { useMasterKey: true } );
if (invite != null && invite != undefined)
{
const deckId = invite.get("deckId");
console.log(deckId);
if (invite.get("invited") === user.getUsername())
{
if (action === "accept")
{
let deckQuery = new Parse.Query("Deck");
await deckQuery.get(deckId, { useMasterKey: true } ).then((deck) =>
{
console.log(deck);
deck.addUnique("collaborators", user.getUsername());
deck.save();
}).catch((error) =>
{
console.log(error); // is always error
});
}
invite.destroy();
return true;
}
}
return false;
});
This gives me the same error:
let deckQuery = new Parse.Query("Deck");
await deckQuery.find({ useMasterKey: true } ).then((deck) =>
{
console.log(deck.length);
}).catch((error) =>
{
console.log(error);
});
OMG im so dumb,
apparently you get this error if you have a typo as well.
I just changed
const action = request.params.actiom;
to
const action = request.params.action;

How do I use createAsyncThunk to repeatedly fetch data automatically?

The goal is to repeatedly fetch generation data when the Id changes...The generation Id changes at the backend
Only AFTER I used redux tool kit and createAsyncThunk, did it stop refreshing generation Id automatically, unless I manually refresh the page (will it show the latest generationId)
The change I've made, so how should I do it? Thanks.
in generationSlice.js
export const getGeneration = createAsyncThunk(
'generation/getGeneration',
async () => {
try {
const resp = await axios(url)
return resp.data
} catch (error) {
return error.response
}
}
)
and
in components/Generation.js
const { generationId, expiration, isLoading } = useSelector((store) => {
return store.generation
})
const dispatch = useDispatch()
useEffect(() => {
dispatch(getGeneration())
}, [generationId])

How to return Stripe coupons using Strapi GraphQL

I've got a Nuxt app with a Checkout page, and on the backend I'm using Strapi GraphQL. I created several coupons in Stripe, and I want to be able to verify the coupons from the Checkout page, but I'm struggling to figure out how to do this. Here's what I have so far:
Frontend (Nuxt)
Cart.vue:
this.$apollo.query({
query: validateCouponQuery,
variables: {
coupon: this.coupon
}
})
validateCoupon.gql:
query($coupon: String!) {
validateCoupon(coupon: $coupon) {
id
name
valid
}
}
Backend (Strapi):
./order/config/routes.json:
{
"method": "GET",
"path": "/orders/validateCoupon",
"handler": "order.validateCoupon",
"config": {
"policies": []
}
}
./order/config/schema.graphql.js:
const { sanitizeEntity } = require('strapi-utils');
module.exports = {
query: `
validateCoupon(coupon: String): Order
`,
resolver: {
Query: {
validateCoupon: {
resolverOf: 'Order.validateCoupon',
async resolver(_, { coupon }) {
const entity = await strapi.services.order.validateCoupon({ coupon });
return sanitizeEntity(entity, { model: strapi.models.order });
}
}
}
}
}
./order/controllers/order.js:
'use strict';
require('dotenv').config();
const stripe = require('stripe')(`${process.env.STRIPE_SECRET_KEY}`);
module.exports = {
validateCoupon: async ctx => {
const { coupon } = ctx.request.body;
console.log('request coupon: ', coupon);
try {
const coupons = await stripe.coupons.list({ limit: 3 }, function (err, coupons) {
console.log('err: ', err);
console.log('coupons: ', coupons);
});
return coupons;
} catch (err) {
console.error('error validating coupon: ', err)
}
}
};
Right now, when I try to run the query in the GraphQL Playground, I get the error strapi.services.order.validateCoupon is not a function.
I'm fairly new to GraphQL... is there a better way to fetch external data than running a query?
****Update****
I've added my order service, which has gotten rid of that original error. The issue now is that even though the service appears to be returning the coupon correctly, the const entity in the schema.graphql.js returns undefined for some reason. I wonder if the resolver can't be async/await?
./order/services/order.js:
'use strict';
const stripe = require('stripe')(`${process.env.STRIPE_SECRET_KEY}`);
module.exports = {
validateCoupon: ({ coupon }) => {
stripe.coupons.list()
.then(coupons => {
return coupons.data.filter(c => {
return (c.name === coupon && c.valid) ? c : null;
});
console.log('found: ', found);
})
.catch(err => console.error(err));
}
};
Well, your code to look up coupons on Stripe looks just fine! Looks like Strapi expects your service to be at ./order/services/order.jsā€”could it be as simple as that? Your example shows it at ./order/controllers/order.js. https://strapi.io/documentation/3.0.0-beta.x/concepts/services.html#custom-services
So I ended up creating a Coupon model in the Strapi content builder. This enabled me to more easily return a Coupon object from my GraphQL query. It's not ideal because I'm having to make sure I create both a Stripe and Strapi coupon object to match, however I also don't anticipate on creating too many coupons in the first place.
My updated code looks like this:
schema.graphql.js:
const { sanitizeEntity } = require('strapi-utils/lib');
module.exports = {
query: `
validateCoupon(coupon: String): Coupon
`,
resolver: {
Query: {
validateCoupon: {
description: 'Validate Stripe coupon',
resolver: 'application::order.order.validateCoupon',
}
}
}
}
./order/controllers/order.js:
'use strict';
require('dotenv').config();
const { sanitizeEntity } = require('strapi-utils');
module.exports = {
validateCoupon: async ctx => {
const coupon = ctx.query._coupon;
const found = await strapi.services.order.validateCoupon({ coupon });
return sanitizeEntity(found, { model: strapi.models.order });
}
};
./order/services/order.js:
'use strict';
const stripe = require('stripe')(`${process.env.STRIPE_SECRET_KEY}`);
module.exports = {
async validateCoupon({ coupon }) {
let foundCoupon = null;
try {
const coupons = await stripe.coupons.list();
const found = coupons.data.filter(c => {
return (c.name === coupon && c.valid) ? c : null;
});
if (found) foundCoupon = found[0];
} catch (err) {
console.error(err);
}
return foundCoupon;
}
};

strapi - restrict user to delete/destroy only data related to him

I would like to write a few lines to prevent a user from deleting data he does not own.
How can I customize the following "destroy" part?
destroy: async (ctx, next) => {
return strapi.services.contactnumber.remove(ctx.params);
}
Thanks in advance and happy easter.
I've do the same for my app, please find below my example code :
findOne: async (ctx) => {
var rent = await strapi.services.rent.fetch(ctx.params);
var user = ctx.state.user;
rent = rent.toJSON ? rent.toJSON() : rent;
if (user.id === rent.tenant.user) {
return rent;
}
else {
return ctx.badRequest(null, 'Forbidden');
}
},
Maybe it's not the best implementation, but it's working fine :)
The keyword "await" is important, because you need to wait the full response before verify the response (otherwise "undefined" will be returned).
I think your code will looks like that :
destroy: async (ctx, next) => {
var contactnumber = await strapi.services.contactnumber.findOne(ctx.params);
contactnumber = (contactnumber.toJSON ? contactnumber.toJSON() : contactnumber);
if (ctx.state.user.id === contactnumber.user) {
return strapi.services.contactnumber.remove(ctx.params);
}
else {
return ctx.badRequest(null, 'Your error message');
}
}
Thanks,

Resources