Retrieve data from the firebase dynamic link - firebase

Im trying to get the data from the generated firebase dynamic link.
I passed Id while generating the dynamic link. I need to get the particular id from the generated dynamic link. Can you please help me.
Where it generates link as :https://thejyotistore.page.link/jNngseAasXzE5SuSA
const ShareLink = ({
fallbackUrl, id, product }) =>
{
const buildLink = async () =>
{
let link = await axios({
method: "POST",
url:
`https://firebasedynamiclinks
.googleapis.com/v1/shortLinks?
key=AIzaSyDNZvtkjAqf8c9esg
gSEzV2 L7. 3vEUv1FfQ`,
headers: {
"Content-Type":
"application/json",
},
data: {
dynamicLinkInfo: {
domainUriPrefix: `https://thejyotistore.page.link`,
link: `https://youtube.com/${id}`,
androidInfo: {
androidPackageName: "com.jyotistore.main",
},
},
},
});
if (link.status === 200 && link.data.hasOwnProperty("shortLink")) {
console.log(link.data.shortLink);
return link.data.shortLink;
}
};
const shareLink = async () =>
{
let shareUrl;
try {
shareUrl = await buildLink();
console.log(shareUrl);
} catch (error) {
console.log(error);
}
try {
if (shareUrl !== "") {
const result = await Share.share({
message: `Hey, ${"\n \n"}I would like to invite you to check out this New App from Jyoti Store. ${"\n \n"} ${product}Download the App now: ${"\n \n"} ${shareUrl}`,
});
}
} catch (error) {
console.log(error);
}
};

Related

NextJS contact form with nodemailer throws Error 500 in Production

I have a simple contact form in a NextJS app and I wanted to switch from emailjs to something custom.
The contact form works perfect in development, but in production(cpanel, not vercel) I get a status 500 error(Internal Server Error). I've researched around and implemented async/await, promises, res.send status and everything I've found but I still can't find a way through.
Here's the post method:
const checkForm = async () => {
try {
const values = await form.validateFields();
fetch('/api/contact', {
method: 'POST',
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify(values)
});
} catch (error) {
console.log('Failed:', error);
}
};
And the /api/contact
import nodemailer from 'nodemailer';
export default async (req, res) => {
const { first_name, last_name, email, phone_number, subject, message } = req.body;
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.EMAIL,
pass: process.env.PASSWORD
}
});
await new Promise((resolve, reject) => {
transporter.verify(function (error, success) {
if (error) {
console.log(error);
reject(error);
} else {
console.log('Server is ready to take our messages');
resolve(success);
}
});
});
const mailOption = {
from: `${email}`,
replyTo: `${email}`,
to: `${process.env.EMAIL}`,
subject: `${subject}`,
html: `<p><strong>Name:</strong> ${first_name + ' ' + last_name}</p>
<p><strong>Email:</strong> ${email}</p>
<p><strong>Phone number:</strong> ${phone_number}</p>
<p><strong>Message:</strong><br /> ${message}</p>
`
};
await new Promise((resolve, reject) => {
transporter.sendMail(mailOption, (err, info) => {
if (err) {
console.error(err);
reject(err);
res.send('error:' + JSON.stringify(err));
} else {
console.log(info);
resolve(info);
res.send('success');
}
});
});
res.status(200).json({ status: 'OK' });
};

Get content related to a user in Strapi

I have a collection in Strapi called projects and I want to be able to fetch only the projects belonging to the currently logged in user. I'm using Next.js with NextAuth on the frontend and I'm currently filtering the results using:
/api/projects?filters[user][id][$eq]=${session.id}
This works fine except the endpoint still allows a user to fetch projects for all users if accessed directly. I'm thinking a better approach would be to setup a custom API endpoint in Strapi which would be something like /api/projects/:user. Is this the best way to acheive this? I've managed to setup a custom endpoint in Strapi using the CLI but I'm not sure what logic needs to go in the controller. Would modifiying an exisiting endpoint be better?
Any advice appreciated, thanks!
Custom endpoint create is good idea. I had same problem. Once i created custom endpoint then i got data with entitiyservice. It's work. Below image is my code.
./scr/api/[collection]/controllers/[collection].js
'use strict';
const { createCoreController } = require('#strapi/strapi').factories;
module.exports = createCoreController('api::user-profile.user-profile', ({ strapi }) => ({
async me(ctx) {
try {
const user = ctx.state.user;
const datas = await strapi.entityService.findMany("api::user-profile.user-profile", {
filters: {
user: {
id: user.id
}
}
})
return datas;
} catch (err) {
ctx.body = err;
}
}
}));
If you will use all endpoints in collection like (create,update,delete,find,findone). You must override the all endpoints . Example is the below.
'use strict';
const { createCoreController } = require('#strapi/strapi').factories;
module.exports = createCoreController('api::education.education', ({ strapi }) => ({
async create(ctx) {
try {
const user = ctx.state.user;
ctx.request.body.data.users_permissions_user = user.id
const datas = await strapi.entityService.create("api::education.education", {
...ctx.request.body
})
return datas;
} catch (err) {
ctx.body = err;
}
},
async update(ctx) {
try {
const user = ctx.state.user;
ctx.request.body.data.users_permissions_user = user.id
const { id } = ctx.params;
const experienceData = await strapi.entityService.findMany("api::education.education", {
filters: {
users_permissions_user: {
id: user.id
},
id: id
}
});
if (experienceData.length === 0) {
return {
data: null,
error: {
message: ''
}
}
}
const datas = await strapi.entityService.update("api::education.education", id, {
...ctx.request.body
})
return datas;
} catch (err) {
ctx.body = err;
}
},
async delete(ctx) {
try {
const user = ctx.state.user;
const { id } = ctx.params;
const experienceData = await strapi.entityService.findMany("api::education.education", {
filters: {
users_permissions_user: {
id: user.id
},
id: id
}
});
if (experienceData.length === 0) {
return {
data: null,
error: {
message: ''
}
}
}
const datas = await strapi.entityService.delete("api::education.education", id)
return datas;
} catch (err) {
ctx.body = err;
}
},
async findOne(ctx) {
try {
const user = ctx.state.user;
const { id } = ctx.params;
const experienceData = await strapi.entityService.findMany("api::education.education", {
filters: {
users_permissions_user: {
id: user.id
},
id: id
}
});
if (experienceData.length === 0) {
return {
data: null,
error: {
message: ''
}
}
}
const datas = await strapi.entityService.findOne("api::education.education", id)
return datas;
} catch (err) {
ctx.body = err;
}
},
async find(ctx) {
try {
const user = ctx.state.user;
const datas = await strapi.entityService.findMany("api::education.education", {
filters: {
users_permissions_user: {
id: user.id
}
}
})
return datas;
} catch (err) {
ctx.body = err;
}
},
}));
No extra endpoints and no extra codes.
Strapi v4
Yes, creating separate endpoint for this task would be great.
Instead of /api/projects/:user using this type of route, use /api/projects as you can get current logged in users details from ctx.state.user
No, Instead of modifying your existing controller create new controller and use that controller to satisfy your needs.
I ended up extending my controller. In src/api/controllers/project.js I made the following changes:
"use strict";
const { createCoreController } = require("#strapi/strapi").factories;
module.exports = createCoreController("api::project.project", {
async find(ctx) {
const user = ctx.state.user;
ctx.query.filters = {
...(ctx.query.filters || {}),
user: user.id,
};
return super.find(ctx);
},
});
Then simply call the /api/projects endpoint.
Answer based on this guide Limit access of Strapi users to their own entries.

refresh access token with apollo client in Next.js

I'm working with next.js and apollo client to get an access token with a refresh token from the server and I searched the web and find apollo-link-token-refresh that does something like silent refresh, so I follow along with example and was happy that after 2 days I finish my project Authentication but no it didn't work. is there any problem in my code?
const refreshLink = new TokenRefreshLink({
accessTokenField: "token",
isTokenValidOrUndefined: () => {
if (!cookie.get("JWT")) {
return true;
}
if (token && jwt.decode(token)?.exp * 1000 > Date.now()) {
return true;
}
},
fetchAccessToken: async () => {
if (!cookie.get("JWT")) {
return true;
}
const response = await fetch(`${NEXT_PUBLIC_SERVER_API_URL}`, {
method: "POST",
headers: {
authorization: token ? "JWT " + token : "",
"content-type": "application/json",
},
body: JSON.stringify({
query: `
mutation {
refreshToken(refreshToken: "${cookie.get("JWTRefreshToken")}") {
token
payload
refreshToken
refreshExpiresIn
}
}
`,
}),
});
return response.json();
},
handleFetch: (newToken) => {
cookie.remove("JWT", { path: "" });
cookie.set("JWT", newToken, {
expires: data.tokenAuth.payload.exp,
secure: process.env.NODE_ENV !== "production",
path: "",
});
},
handleResponse: (operation, accessTokenField) => (response) => {
if (!response) return { newToken: null };
return { newToken: response.data?.refreshUserToken?.token };
},
handleError: (error) => {
console.error("Cannot refresh access token:", error);
},
});
function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === "undefined",
link: authLink.concat(refreshLink).concat(
new HttpLink({
uri: process.env.NEXT_PUBLIC_SERVER_API_URL,
credentials: "same-origin",
}),
),
cache
})
)

How to test cyclejs http driver?

Suppose I have an API that return user detail:
/api/get_user/1
{
"status": 200,
"data": {
"username": "username1",
"email": "username#email.com"
}
}
And a "main function" like this:
function main (sources) {
const request$ = sources.ACTIONS
.filter(action => action.type === 'GET_USER_REQUEST')
.map(action => action.payload)
.map(payload => ({
category: 'GET_USER_REQUEST',
url: `${BASE_URL}/api/get_user/${payload.userId}`,
method: 'GET'
}))
const action$ = sources.HTTP
.select('GET_USER_REQUEST')
.flatten()
.map(response => response.data)
const sinks = {
HTTP: request$,
LOG: action$
}
return sinks
}
For testing the "ACTION" source, I can simply made an xstream observable
test.cb('Test main function', t => {
const actionStream$ = xs.of({
type: 'GET_USER_REQUEST',
payload: { userId: 1 }
})
const sources = { ACTION: actionStream$ }
const expectedResult = {
category: 'GET_USER_REQUEST',
url: `${BASE_URL}/api/get_user/${payload.userId}`,
method: 'GET'
}
main(sources).HTTP.addEventListener({
next: (data) => {
t.deepEqual(data, expectedResult)
},
error: (error) => {
t.fail(error)
},
complete: () => {
t.end()
}
})
})
The question is. Is it possible to do the same thing (using plan xstream observable)
to test cycle-http driver without a helper from something like nock?
Or is there a better way to test something like this?
You can mock out the HTTP source like so:
test.cb('Test main function', t => {
const actionStream$ = xs.of({
type: 'GET_USER_REQUEST',
payload: { userId: 1 }
})
const response$ = xs.of({
data: {
status: 200,
data: {
username: "username1",
email: "username#email.com"
}
}
});
const HTTP = {
select (category) {
// if you have multiple categories you could return different streams depending on the category
return xs.of(response$);
}
}
const sources = { ACTION: actionStream$, HTTP }
const expectedResult = {
category: 'GET_USER_REQUEST',
url: `${BASE_URL}/api/get_user/${payload.userId}`,
method: 'GET'
}
main(sources).HTTP.addEventListener({
next: (data) => {
t.deepEqual(data, expectedResult)
},
error: (error) => {
t.fail(error)
},
complete: () => {
t.end()
}
})
})
Really, we should have a mockHTTPSource helper to make this a bit easier. I have opened an issue to that effect. https://github.com/cyclejs/cyclejs/issues/567
If you want to test that certain things happen at the correct time, you could use this pattern in conjunction with #cycle/time.
http://github.com/cyclejs/time

redux observable: Why don`t can get all actions in test

I'm trying to test a 'redux observable epic' but the test fail because not all actions are in store.getActions() the strange is the store.dispatch function runs.
Epic and actions
export const VERIFY_SESION = 'auth/VERIFY_SESION';
export const SET_POLICIES_ACCEPTED = 'auth/SET_POLICIES_ACCEPTED';
export const AUTHENTICATE = 'auth/AUTHENTICATE';
export function setPoliciesAccepted(wereAccepted: boolean) {
return {
wereAccepted,
type: SET_POLICIES_ACCEPTED,
};
}
export function verifySesion() {
return {
type: VERIFY_SESION,
};
}
export function authenticate(token) {
return {
token,
type: AUTHENTICATE,
};
}
export function verifySesionEpic(action$, store) {
return action$
.ofType(VERIFY_SESION)
.switchMap(async () => {
try {
store.dispatch(setBlockLoading(true));
const token = await AsyncStorage.getItem('token');
if (token !== null) {
store.dispatch(setBlockLoading(false));
return authenticate(token);
}
const policiesWereAccepted = await AsyncStorage.getItem('policiesWereAccepted');
store.dispatch(setBlockLoading(false));
return setPoliciesAccepted(policiesWereAccepted);
} catch (error) {
return setMessage(error.message);
}
});
}
test
describe('actions/auth', () => {
let store;
const asyncStorageGetStub = stub(AsyncStorage, 'getItem');
beforeEach(() => {
store = mockStore();
});
afterEach(() => {
asyncStorageGetStub.restore();
});
it('Should call authenticate if token', () => {
const token = 'mitoken';
asyncStorageGetStub.withArgs('token').returns(Promise.resolve(token));
store.dispatch(verifySesion());
expect(store.getActions()).toContain({ type: AUTHENTICATE, token });
});
});
Test result
1) "actions/auth Should call epic for verifySesion:
Error: Expected [ { type: 'auth/VERIFY_SESION' } ] to include { token: 'mitoken', type: 'auth/AUTHENTICATE' }"
Note
im sure that the conditional token !== null pass
I was to add a timeout before getAction because the 'AUTHENTICATE' actions is added after.
it('Should call authenticate if token', (done) => {
const token = 'mitoken';
asyncStorageGetStub.withArgs('token').returns(Promise.resolve(token));
store.dispatch(verifySesion());
setTimeout(() => {
expect(store.getActions()).toContain({ type: AUTHENTICATE, token });
done();
}, 1000);
});

Resources