Following the instructions I get a valid token from my front end (can see in dev tools):
window.grecaptcha
.execute(captchaPkey, { action: 'contact' })
.then((token) => {
// this is what I POST to my API
So in my React front end:
send = (event) => {
event.preventDefault()
this.setState({ busy: true })
window.grecaptcha.ready(() => {
window.grecaptcha
.execute(captchaPkey, { action: 'contact' })
.then((token) => {
// successfully get token
const payload = {
token,
name: this.state.name,
to: this.props.to,
email: this.state.email,
message: this.state.message,
}
// now I'm sending the payload to my API
// My API
update(`${api}/contact/`, {
method: 'POST',
body: JSON.stringify(payload)
}, null)
.then(data => {
this.setState({ busy: false, result: 'Email sent' });
})
.catch(error => {
this.setState({ busy: false, error: error.message });
});
})
})
}
my API controller
async function verifyCaptcha(token) {
return await axios.post('https://www.google.com/recaptcha/api/siteverify', {
secret: process.env.CAPTCHA_PKEY,
response: token
})
}
async function contact({ token, to, name, email, message }) {
const result = await verifyCaptcha(token)
if (!result || !result.data || !result.data.success) {
// always get an error here
throw new Error('Invalid captcha')
}
let targetEmail = 'default#emailaddress'
if (to !== 'admin') {
const user = await User.findOne({ username: to }, { email }).exec()
if (!user) {
throw new Error('User does not exist')
}
targetEmail = user.email
}
// rest of send
}
On my API POST endpoint sends to https://www.google.com/recaptcha/api/siteverify with the body of:
{
secret: process.env.CAPTCHA_PKEY,
response: token
}
Yet I always get "missing-input-response", "missing-input-secret" error. Is this because v3 is new? Still bugs?
Realised in the documentation it states "post params" not post body haha.
Related
I have to verify OTP in graphql POST request using cy.request() in cypress.
I want to create a suite so it will enter a new email and get OTP from that email and after that, I want to use that email and OTP in my query so it will verify using request.
describe('Sign Up Test', function () {
beforeEach("Load", function () {
Cypress.Cookies.preserveOnce('session_id', 'event_id', 'uuid', '_cltk', 'amp_394a99_outsized.site', '_clsk', 'amp_394a99')
cy.fixture("data").then((data) => {
this.key = data
})
})
it('Sign up', function () {
cy.visit('/')
cy.xpath('//button[text()=" Sign Up with Email"]').click()
cy.get('#email').type(email.toLocaleLowerCase())
cy.fixture("data.json").then(profile => {
profile.email = email
cy.writeFile("cypress/fixtures/data.json", profile);
cy.get('.ant-btn').click()
cy.wait(2000)
})
})
it('Check Otp', function () {
cy.visit("https://www.mailinator.com/", { timeout: 30000 })
cy.readFile('cypress/fixtures/Data.json').then((profile) => {
cy.get("#search").type(profile.email)
})
cy.xpath('//*[text()="GO"]').click()
cy.wait(2000)
cy.contains('table tbody tr', 'OTP').click() // find the right email
cy.get('#html_msg_body') // iframe
.its('0.contentDocument.body').should('not.be.empty') // wait for loading
.then(console.log) // works with this but errors without - totally weird
.wait(2000)
.find("table > tbody > tr:nth-child(3) > td > h2")
.then($h2 => {
const OTP = $h2.text()
cy.fixture("data.json").then(profile => {
profile.OTP = OTP
cy.writeFile("cypress/fixtures/data.json", profile);
})
})
cy.request({
method: "POST",
url: "https://api.outsized.site/graphql",
failOnStatusCode: false,
body: {
query: "mutation { verifyEmailOtp(email: " + this.key.email + ", otp: " + this.key.OTP + "){ message } }"
}
}).then((res) => {
expect(res.status).to.eq(200)
});
})
it.only('Sign up', function () {
const otpQuery = `mutation {
verifyEmailOtp(email: "test.01#getnada.com", otp: 3262)
{ message }
}`
cy.request({
method: "POST",
url: "https://api.outsized.site/graphql",
headers:{
'Content-Type': 'text/plain'
},
body: {
query: "mutation: { verifyEmailOtp(email: " + this.key.email + ", otp: " + this.key.OTP + "){ message } }"
},
failOnStatusCode: false,
}).then((res) => {
expect(res.status).to.eq(200)
});
// Cypress.Cookies.preserveOnce('session_id', 'event_id', 'uuid', '_cltk', 'amp_394a99_outsized.site', '_clsk', 'amp_394a99')
cy.visit('/')
cy.xpath('//button[text()=" Sign up with email"]').click({ force: true })
cy.wait(2000)
cy.fixture("data.json").then(profile => {
cy.get('#email').type(profile.email)
})
cy.wait(2000)
cy.get('.ant-btn').click()
cy.wait(3000)
cy.reload()
})
})
This is my test, first, one generates random emails using the faker library. and send OTP in that email and also save the email into my data file.
The second one gets OTP from that email and saves it to my data file.
And the third one is making a request using email and OTP.
My output:
I have a nextjs app with a backend api where I am sending an email out.
I have seen a couple of other posts with the same issue, have tried their resolutions and not sure what I am missing.
Any insight is appreciated.
The code in the API is below.
const nodemailer = require('nodemailer');
export default function (req, res) {
const mailData = {
from: 'xxxxx',
to: req.body.email,
subject: 'Message to Full On Consulting',
text: req.body.message,
html: '<div>'+req.body.message+'</div>'
}
sendMail(mailData)
.then((result) => {
console.log('Email sent...', result);
res.status(200).json({ status: 'SUCCESS' })
})
.catch((error) => console.log('Error ... ' + error.message));
}
async function sendMail(mailData) {
try {
let transport = nodemailer.createTransport({
host: "mail.xxxxxxxxxx.com",
port: 587,
secure: false,
auth: {
user: process.env.GMAIL_UID,
pass: process.env.GMAIL_PW
}
});
const result = await transport.sendMail(mailData)
return result;
} catch (error) {
console.log("CATCH ERROR: " + error)
return error;
}`enter code here`
}
I wrapped the sendmail call in a promise and that seems to have worked.
var promise = new Promise( (resolve, reject) => {
let result = transport.sendMail(mailData);
});
promise.then( result => {
console.log("PRomise Success ...");
}, function(error) {
console.log("Promise Failure...");
});
I tried using async/await instead of the callback for reading the Gmail
Here is the code snippet
const {google} = require('googleapis');
async function getRecentMessageBody(auth) {
const gmail = google.gmail({version: 'v1', auth});
try{
const messageId = await gmail.users.messages.list({
userId: 'me',
labelIds: 'INBOX',
maxResults: 1
});
const message = await gmail.users.messages.get({
userId: 'me',
id: messageId.data.messages[0].id,
format : 'full'
});
const value = base64url.decode(message.data.payload.body.data);
console.log(messageId);
//return value ;
}
catch(error) {
console.log('Error occurs while reading mail :'+ error);
throw error;
}
}
But the messageId is undefined
whereas if i use
gmail.users.labels.list({
userId: 'me',
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
const labels = res.data.labels;
if (labels.length) {
console.log('Labels:');
labels.forEach((label) => {
console.log(`- ${label.name}`);
});
} else {
console.log('No labels found.');
}
});
how to fix the issue??
use promisfy to convert callback to promises
The problem:
I am able to successfully upload an image to firebase storage, but when I try to sign-out, then sign-in again, I am stucked on the log-in page. and after few minutes this error appears
This is my code on fetching the image and log-in
if (currentUser != null) {
uid = currentUser.uid;
const db = firebase.firestore();
const docRef = db.collection("users").doc(uid);
console.log("uid")
console.log(uid)
console.log("currentUser")
console.log(currentUser)
console.log("docRef")
console.log(docRef)
docRef.get().then((doc) => {
console.log("doc");
console.log(doc);
if (doc.exists) {
console.log("Document data:", doc.data());
const userData = doc.data();
const imageRef = firebase.storage().ref(`/userProfilePictures/${uid}`).child('profile.jpg');
imageRef.getDownloadURL().then(function(url) {
dispatch({ type: GET_PROFILE_PICTURE, payload: url })
dispatch({ type: GET_USER_DATA, payload: userData});
Actions.home();
}).catch((error) => {
dispatch({type: GET_PROFILE_PICTURE, payload: ''})
console.log(error);
})
} else {
console.log("No such document!");
}
}).catch((error) => {
console.log("Error getting document:", error);
});
}else {
console.log('something went wrong');
}
})
.catch((error) => {
loginUserFail(dispatch)
const errorCode = error.code;
const errorMessage = error.message;
console.log(errorMessage);
});
After loggin in again, it seems that the user is authenticated, but It can't execute this line docRef.get().then((doc) => { there is no error on the console.log.
And then if you try to reload again, then sign-in again you can see the newly uploaded image.
"By default, an admin-on-rest app doesn’t require authentication".
I have written an application with AOR and Loopback API, etc, and it works well. Except for one thing, I can't turn on turn on authentication. Any username/password will work, just like in the Demo.
From what I can see all required components load, AuthClient etc., Loopback is configured and is waiting for user authorization requests but never gets any.
I copy/pasted a lot of Demo's parts...
Any hints please?
I use the unchanged authClient from kimkha aor loopback
import storage from './storage';
export const authClient = (loginApiUrl, noAccessPage = '/login') => {
return (type, params) => {
if (type === 'AUTH_LOGIN') {
const request = new Request(loginApiUrl, {
method: 'POST',
body: JSON.stringify(params),
headers: new Headers({ 'Content-Type': 'application/json' }),
});
return fetch(request)
.then(response => {
if (response.status < 200 || response.status >= 300) {
throw new Error(response.statusText);
}
return response.json();
})
.then(({ ttl, ...data }) => {
storage.save('lbtoken', data, ttl);
});
}
if (type === 'AUTH_LOGOUT') {
storage.remove('lbtoken');
return Promise.resolve();
}
if (type === 'AUTH_ERROR') {
const { status } = params;
if (status === 401 || status === 403) {
storage.remove('lbtoken');
return Promise.reject();
}
return Promise.resolve();
}
if (type === 'AUTH_CHECK') {
const token = storage.load('lbtoken');
if (token && token.id) {
return Promise.resolve();
} else {
storage.remove('lbtoken');
return Promise.reject({ redirectTo: noAccessPage });
}
}
return Promise.reject('Unkown method');
};
};