I'm using the advanced-http cordova plugin. Followed all their steps in their GitHub repo.
But when I try to run my code an error pops up:
missing mandatory "onFail" callback function
Here's how my code looks like:
cordova.plugin.http.post('http://127.0.0.1:5000/api/register', {
username: this.username,
password: this.password,
firstname: this.firstname,
middlename: this.middlename,
lastname: this.lastname,
birthday: this.birthday,
age: this.age,
contact: this.contact,
address: this.address,
prisoner: this.prisoner
}, response => {
try {
response.data = JSON.parse(response.data);
// prints test
console.log(response.data.message);
} catch(e) {
console.error('JSON parsing error');
}
}, response => {
// prints 403
console.log(response.status);
//prints Permission denied
console.log(response.error);
});
What am I missing here? Please help.
you are missing headers parameter in your call. According to docs linked in the question:
Takes a URL, data, and headers.
cordova.plugin.http.post('http://127.0.0.1:5000/api/register', {
username: this.username,
password: this.password,
firstname: this.firstname,
middlename: this.middlename,
lastname: this.lastname,
birthday: this.birthday,
age: this.age,
contact: this.contact,
address: this.address,
prisoner: this.prisoner
},
{ //your_headers_here
},
response=> {//success callback
},
response=> {//error callback
});
Related
I get this to work locally, but get a Response Error: Unauthorized on Vercel.
I've created a Single Sender Verification on Sendgrid which is verified.
I've tried creating a new API key on Sendgrid but it still dosen't work.
I'm out of options.
This is my code in the api route:
import type { NextApiRequest, NextApiResponse } from "next";
const sgMail = require("#sendgrid/mail");
type EmailData = {
to: string;
from: string;
subject: string;
text: string;
html: string;
};
type DataResponse = {
data?: any;
success: boolean;
error?: string;
};
const emailAddress = process.env.SENDGRID_EMAIL as string;
const emailAddressTo = process.env.SENDGRID_EMAIL_TO as string;
sgMail.setApiKey(process.env.SENDGRID_API_KEY as string);
export default async function _(req: NextApiRequest, res: NextApiResponse<DataResponse>) {
if (req.method !== "POST") {
res.status(400).json({ success: false, error: "Invalid request" });
return;
}
const data = JSON.parse(req.body);
const { name, email, phone = "", message = "" } = data;
console.log("sgMail", sgMail);
console.log("--------------");
console.log("process.env.SENDGRID_API_KEY", process.env.SENDGRID_API_KEY);
console.log("--------------");
console.log("SENDGRID_EMAIL", process.env.SENDGRID_EMAIL);
console.log("--------------");
console.log("SENDGRID_EMAIL_TO", process.env.SENDGRID_EMAIL_TO);
console.log("--------------");
const text = `
Name: ${name} \r\n
Email: ${email} \r\n
Phone: ${phone} \r\n
message: ${message} \r\n
`;
let emailData: EmailData = {
to: emailAddressTo,
from: emailAddress,
subject: "Form submission",
text: text,
html: `<div>${text.replace(/\r\n/g, "<br>")}</div>`,
};
try {
await sgMail.send(emailData);
} catch (error) {
console.log(error);
res.status(400).json({ success: false, error: "Error while sending email" });
return;
}
res.status(200).json({ success: true, data: {} });
}
This is the log from the server with the error messages:
sgMail MailService {
client: Client {
auth: 'Bearer HIDDEN BUT ITS THERE',
impersonateSubuser: '',
defaultHeaders: {
Accept: 'application/json',
'Content-Type': 'application/json',
'User-Agent': 'sendgrid/7.7.0;nodejs'
},
defaultRequest: {
baseUrl: 'https://api.sendgrid.com/',
url: '',
method: 'GET',
headers: {},
maxContentLength: Infinity,
maxBodyLength: Infinity
}
},
substitutionWrappers: [ '{{', '}}' ],
secretRules: [],
MailService: [class MailService]
}
--------------
process.env.SENDGRID_API_KEY HIDDEN BUT ITS THERE
--------------
SENDGRID_EMAIL HIDDEN BUT ITS THERE
--------------
SENDGRID_EMAIL_TO: HIDDEN BUT ITS THERE
--------------
ResponseError: Unauthorized
at node_modules/#sendgrid/client/src/classes/client.js:146:29
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
code: 401,
response: {
headers: {
server: 'nginx',
date: 'Sun, 19 Feb 2023 20:57:56 GMT',
'content-type': 'application/json',
'content-length': '97',
connection: 'close',
'access-control-allow-origin': 'https://sendgrid.api-docs.io',
'access-control-allow-methods': 'POST',
'access-control-allow-headers': 'Authorization, Content-Type, On-behalf-of, x-sg-elas-acl',
'access-control-max-age': '600',
'x-no-cors-reason': 'https://sendgrid.com/docs/Classroom/Basics/API/cors.html',
'strict-transport-security': 'max-age=600; includeSubDomains'
},
body: { errors: [Array] }
}
}
Vercel deployments use dynamic IP addresses due to the dynamic nature of the platform and in Sendgrid their IP Access management was on, which meant that all requests from Vercel were blocked..
SOLUTION:
You can disable IP Access Management to reopen account access to any IP address and no longer maintain a list of allowed addresses.
From the Settings > IP Access Management page, click Disable Allow List.
A dialog will open asking you to confirm the decision. Click Disable.
I am using Next.js and Next Auth to talk to my backend C# ASP.NET API.
My API's response is the following DTO:
{
"data": {
"accessToken": "string",
"refreshToken": "string",
"email": "user#example.com",
"username": "string",
"roles": [
"string"
]
},
"success": true,
"message": "string"
}
I am having a hard time getting that info into the next auth session so that I can grab it with useSession().
I'd also like to be able to display the API "message" to the user in the login form. Incase their account is locked or whatever.
This is what I have:
[...nextauth].js
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { API_URL } from "#/constants";
export const authOptions = {
// Configure one or more authentication providers
providers: [
// Add Your Providers Here
CredentialsProvider({
name: "Credentials",
credentials: {
username: { label: "Username", type: "text", placeholder: "jsmith" },
password: { label: "Password", type: "password" },
},
async authorize(credentials, req) {
const { usernme, password } = credentials;
const body = JSON.stringify({
username,
password,
});
// Login request to our API.
const res = await fetch(`${API_URL}/Login`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json; charset=utf-8",
},
body: body,
});
const data = await res.json();
// Our API's response contains
/*
{
"data": {
"accessToken": "string",
"refreshToken": "string",
"email": "user#example.com",
"username": "string",
"roles": [
"string"
]
},
"success": true,
"message": "string"
}
*/
const user = {
success: data.success,
message: data.message,
email: data.data.email,
username: data.data.username,
accessToken: data.data.accessToken,
refreshToken: data.data.refreshToken,
roles: data.data.roles,
};
// EVERYTHING TO HERE IS GOOD!
// I CAN GET THE user OBJECT FILLED.
if (res.ok && user) {
return user; //<---- is this actually returning the full user object to the session?
} else {
return null;
}
},
}),
],
pages: { signIn: "/login" },
};
export default NextAuth(authOptions);
Navbar Links:
<Nav.Link as={Link} href='/login' onClick={() => signIn()}>Login</Nav.Link>
<Nav.Link as={Link} href='/signout' onClick={() => signOut({callbackUrl: '/'})}>Signout</Nav.Link>
Login form:
// Get data from the form.
const nextAuthSettings = {
username: event.target.username.value,
password: event.target.password.value,
redirect: true,
callbackUrl: "/dashboard",
};
// Send the form data to Next Auth
const result = await signIn("credentials", nextAuthSettings);
// Error Handling
// THIS DOES NOT WORK
// I don't think signIn() returns a copy of the user object unfortunately...
if (!result.success) {
// Display the API Error Message On The Page
setErrorMsg(result.message);
}
And then in various pages, when I want to access the user object I am doing this :
import { useSession } from "next-auth/react";
const { data: session } = useSession();
// This only shows the email
<span>{session?.user.email}</span>;
// It looks like a JWT or something when I console log it
{
"user": {
"email": "users#email.com"
},
"expires": "2023-03-16T12:39:28.120Z"
}
Any help appreciated!
I need to be able to access the user object my API is returning throughout my app.
At the moment I'm just getting this session.user.email and nothing else ??
it's like I am not mapping the API's response to whatever Next Auth wants me to create...
you have to use callbacks :
callbacks: {
async jwt({ user, token }) {
// update token from user
if (user) {
token.user = user;
}
// return final_token
return token;
},
async session({ session, token }) {
// update session from token
session.user = token.user;
return session;
},
},
Now you can access your session with useSession() and your token with getToken()
How can i create a simple reset password using next auth Credential provider with mongo db
i have user schema like this
const userSchema = new mongoose.Schema<UserSchemaType>(
{
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
img: { type: String, required: true },
isAdmin: { type: Boolean, required: true, default: false },
},
{
timestamps: true,
}
);
my next auth look like this
providers: [
CredentialsProvider({
async authorize(credentials) {
await db.connect();
const user = await User.findOne({
email: credentials.email,
});
if (user && bcryptjs.compareSync(credentials.password, user.password)) {
return {
_id: user._id,
name: user.name,
email: user.email,
image: user.img,
isAdmin: user.isAdmin,
};
}
throw new Error('Invalid email or password');
},
}),
],
});
is there a simple example for implementing reset password with the next auth
From the docs - https://next-auth.js.org/providers/credentials
The functionality provided for credentials based authentication is
intentionally limited to discourage use of passwords due to the
inherent security risks associated with them and the additional
complexity associated with supporting usernames and passwords.
Probably you can use the Email Provider and customise if you really want this feature.
https://next-auth.js.org/configuration/providers/email
I'm trying to register users using node and mongo but I get this ValidationError:
unhandledPromiseRejectionWarning: ValidationError: user validation failed: password: Path password is required., username: Path username is required., email: Path email is required.
this is my signup function.
exports.signup = async function (request, res, next) {
try {
let user = await db.User.create(request.body);
console.log(user);
let { id,email,username } = user;
let token = jwt.sign({
id,
email,
username
},
process.env.SECRET_KEY
);
return res.status(200).json({
id,
username,
token
})
} catch (err) {
if (err.code === 11000) {
err.message = "sorry, username/email are token";
}
return next({
status: 400,
message: err.message
})
}
this is my user model
const userSchema = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true,
},
username: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true,
},
profileImageUrl: {
type: String,
},
messages:[{
type:mongoose.Schema.Types.ObjectId,
ref:'Message'
}]
})
userSchema.pre('save', async function (next) {
try {
if (!this.isModified('password')) {
return next();
}
let hashedPassword = await bcrypt.hash(this.password, 10);
this.password = hashedPassword;
return next();
} catch (err) {
return next(err);
}
});
const User = mongoose.model("user", userSchema);
module.exports = User;
NOTE: I'm using Postman to test this.
So yeah I found the problem. the fields are required so if you try to insert a new user with empty fields you get that error. The fields were empty because The 'body-parser' middleware only handles JSON and urlencoded data, not multipart. So I had to change my index file to
app.use(bodyParser.urlencoded({
extended: true
}));
I also changed the content type in Postman to "X-www-form-urlencoded". Now the request body is populated and the user is inserted correctly
I also faced this error.
In your user model remove required:true in all fields like this:
email: {
type: String,
unique: true
}
Please help me. I have been working for days trying to fix this error and keep ending back up at the same click handler error "user not defined" I just can't figure out what it means... this is a vuejs/vuex/vuetify/firestore project. Please any help would be appreciated.
relevant code from store/index.js
updateUser({ commit, state },
payload) {
commit('setLoading', true);
commit('clearError');
firebase
.firestore()
.collection('users').doc(`users/${user.uid}`).add()
.then((data, payload) => {
const key = data.key;
let displayName = payload.name;
let address = payload.address;
let city = payload.city;
let state1 = payload.state1
let zip = payload.zip
let country = payload.country
let company = payload.company
let email = payload.email
let phoneNumber = payload.phone
commit('updateUser', {
id: key,
name: displayName,
phone: phoneNumber,
email: email,
address: address,
city: city,
state1: state1,
zip: zip,
country: country,
company: company
})
}).catch(err => {
console.log(err)
})
},
Component code...
methods: {
onUpdate() {
this.$store.dispatch("updateUser", {
email: this.email,
name: this.name,
company: this.company,
address: this.address,
city: this.city,
state1: this.state1,
zip: this.zip,
country: this.zip,
phone: this.phone,
});
},
Assuming user is a state property, ie
state: {
loading: false,
errors: [],
user: null // 👈 here
},
then your Firestore docref should be
.doc(`users/${state.user.uid}`)
Since your action performs asynchronous operations, you should consider making it composable by having it return the promise, eg
updateUser({ commit, state }, payload) {
commit('setLoading', true)
commit('clearError')
return firebase.firestore()... // 👈 note the "return" here