tcomb-form-native set error dynamically - react-native

Assume I have login form with the following fields:
const Email = t.refinement(t.String, (str) => {
const reg = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
return reg.test(str);
});
const Password = t.refinement(t.String, (str) => {
return str.length >= 6; // minimum password length should be 6 symbols
});
const Person = t.struct({
email: Email,
password: Password,
});
The data user enters into the fields validates and then I send a request to the authentication server and the server validates received data additionally and it turns out that there is no user with such credentials. So it return according response:
{
success: false,
data: { password: ['User with such credentials is not found.'] }
}
The question is, how can I set dynamically error to tcomb property? Something like:
this.refs.form.getComponent('password').refs.input.addError(someError);
Is it possible?

In case someone is still looking for an answer, binding the "error message" field option to the internal state of the surrounding component should work. For example:
render() {
// ... rest of code omitted
let formOptions = {
fields: {
email: {
hasError: this.state.emailHasError,
error: this.state.emailErrorMessage
}
}
};
return (<Tcomb.form.Form
ref="myForm"
options={formOptions}
/>);
}
And then on receiving server response, you can update the main component state, like:
this.setState({
emailHasError: true,
emailErrorMessage: 'Invalid email address'
});

Related

How can I send multiple emails (around 100) with different email body using amazon ses in NodeJS?

I am trying to send emails to multiple users with email body like
dear {{username}},
/.
....
Your email is {{email}}
...
.
/
how can I do those any ideas, I saw the custom templates for amazon ses but I have 100+ users so how will it be done ?
You can use SES bulk templated emails.
Create a template for your emails.
const AWS = require("aws-sdk");
const ses = new AWS.SES({
accessKeyId: <<YOUR_ACCESS_KEY>>,
secretAccessKey: <<YOUR_ACCESS_KEY>>,
region: <<YOUR_ACCESS_KEY>>
});
const params = {
Template: {
TemplateName: "MyTemplate",
SubjectPart: "Test mail for {{username}}!",
HtmlPart: "<p>Dear {{username}}</p>, <p>Your email is {{email}}.</p>"
}
}
ses.createTemplate(params, (err, data) => {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
Once it is done you would see the MyTemplate under Email templates of SES console. We no longer needed template creating part of the code.
Now we can send the email using the following.
const users = [{username:"max", email: "max#m.com"},{username: "mosh", email:"mosh#h.com"}] // sample array of users
let destinations = []
for (const user of users) {
destinations.push({
Destination: {
ToAddresses: [user.email]
},
ReplacementTemplateData: JSON.stringify({
username: user.username, // This will provide the value for username in template
email: user.email // This will provide the value for email in template
})
});
}
const params = {
Source: "sender#xyz.com", // sender email
Template: "MyTemplate", // Template name we have created
Destinations: destinations,
DefaultTemplateData: JSON.stringify({
username: '', // default value for username
email: '' // default value for email
})
}
ses.sendBulkTemplatedEmail(params, (err, data) => {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
Make sure you have given the ses:createTemplate and ses:sendBulkTemplatedEmail permissions for the IAM user before running this.
For more info see here.

How to properly store a CognitoUser?

I'm working on a simple React/Typescript application to test Cognito and I'm running into some problems handling the user, I have a function that gets the user like so:
/* CognitoUtils.tsx */
import UserPool from './UserPool';
export const getCognitoUser = (phone: string): CognitoUser => {
const userData: ICognitoUserData = {
Username: phone,
Pool: UserPool,
};
return new CognitoUser(userData);
}
I have the UserPool defined in a separate file like so:
/* UsePool.tsx */
import { ICognitoUserPoolData, CognitoUserPool } from "amazon-cognito-identity-js";
const poolData: ICognitoUserPoolData = {
UserPoolId: 'XXX',
ClientId: 'XXX',
Storage: window.sessionStorage
};
const userPool = new CognitoUserPool(poolData);
export default userPool;
And this is the code I use to sign in:
/* CognitoUtils.tsx */
export const signIn = (phone: string) => {
var authenticationDetails = new AuthenticationDetails({
Username: phone,
Password: 'XXXX',
});
const user = getCognitoUser(phone);
user.authenticateUser(authenticationDetails, {
onSuccess: function(session: CognitoUserSession) {
console.log("Succesfully signed in", session, "current user", user);
},
onFailure: function(error) {
console.log("Error while signing in", error);
},
});
}
This is working fine, the user and session objects are printed without a problem.
I have a button for signing out that calls this function:
/* CognitoUtils.tsx */
export const signOut = (phone: string) => {
var user = getCognitoUser(phone);
user.getSession((err: any, session: CognitoUserSession) => {
console.log("Getting session error", err, "session:", session);
user.globalSignOut({
onSuccess: (msg: string) => {
console.log("Succesfully signed out", msg);
},
onFailure: (err: globalThis.Error) => {
console.log("Error while signing out", err);
}
});
});
}
This causes the following error on user.getSession():
Getting session error Error: Local storage is missing an ID Token, Please authenticate
Despite having an id token in my local storage (which is generated on sign in), I have tried saving the user in a shared variable in the same file, saving it on a redux store and even converting the object into a json and saving using localStorage, the closes I've ever got to have this working is the signOut function working after signIn but the user breaking if I refresh the page in between.
My question is, what is the proper way of storing/retrieving this user?
This is the closest I've found to my error but even after moving the UsePool to a separate file this still happens.
This is the tutorial I've been following.
Any help is greatly appreciated.

Error [ERR_HTTP_HEADERS_SENT] : Cannot set headers after they are sent to the client

app.post("/login", async (req, res) => {
// Destructure Req Body
const { email, password } = req.body;
// Validate Body
if (!email || !password) {
res.status(400).json({ success: false, message: "PARAMS_MISSING" });
}
// Build the SQL query
const query = `SELECT * FROM user WHERE email = "${email}"`;
// Get the user from DB
const user = await db(query);
// Check if password is valid
const isPasswordValid = decryptPassword(user.hash_password, password);
// Return if password is not valid
if (!isPasswordValid) {
res.status(401).json({ success: false, message: "INAVLID_PASSWORD" });
}
// Generate Token
const token = generateToken({ id: user.id, email: user.email });
// Save Cookie
res.cookie("token", token, { maxAge: 900000, httpOnly: true });
res.end();
// Return
res.json({ success: true, message: "USER_AUTHENTICATED" });
});
UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
I m getting this error again n again idk what to do i m beginner,
I'm facing this weird issue in NodeJS when using with Passport.js, Express. Basically, I get an error saying "Cannot set headers after they are sent to the client" even though I don't send more than one header.
This error means the 'res' object respond twice. E.g: in your '// Validate body' if the password or email are missing your http connection respond 'res.status().json().'(note that is closing the http connection), but as you didn't stop the execution of the code, it carries on then it may respond a second time in the // Return if password is not valid which create the err as the header can not be set twice and the connection is already close.
Than more here you error is Unhandled, as an Async function reject, the error must be handle, wrapping the code in a try{} catch(e){} will fix it.
So that should fix your issues
app.post("/login", async (req, res) => {
try{
// Destructure Req Body
const { email, password } = req.body;
// Validate Body
if (!email || !password) {
res.status(400).json({ success: false, message: "PARAMS_MISSING" });
return // stop execution of the function
}
// Build the SQL query
const query = `SELECT * FROM user WHERE email = "${email}"`;
// Get the user from DB
const user = await db(query);
// Check if password is valid
const isPasswordValid = decryptPassword(user.hash_password, password);
// Return if password is not valid
if (!isPasswordValid) {
res.status(401).json({ success: false, message: "INAVLID_PASSWORD" });
return // stop exec of the function
}
// Generate Token
const token = generateToken({ id: user.id, email: user.email });
// Save Cookie
res.cookie("token", token, { maxAge: 900000, httpOnly: true });
res.end();
// Return
res.json({ success: true, message: "USER_AUTHENTICATED" });
} catch(err) {
console.error(err) // code to handle the err
}
});
But still, a problem remain as at the end of your script, you have a res.end()(which terminate the connection) and right after a res.json() which will fail as the connection has been close the line before (than more the statusCode is missing)

How I get & validate the username and password in SQL Management using API?

I created my login page and i want to validate the username and password. Then i need to get the user details using API from the database. please send me a coding using ionic-3 and angular-2.
I already tried in my SQL. But i want it in SQL management. In the below coding i send the parameters using post method and it will get at back end and validate with already registered username and password.
Username: any;
Password: any;
data:string;
constructor( ){}
//declaration of object//
var headers = new Headers();
headers.append('Accept', 'application/json');
headers.append('Content-Type', 'application/json' );
let option = new RequestOptions({headers: headers });
let data = {
username: this.Username.value,
password: this.Password.value
};
let loader = this.loading.create({
spinner: 'bubbles',
duration: 1000
});
//API call//
loader.present().then(() => {
this.http.post('')
.map(res => res.json())
.subscribe(res => {
console.log(res)
loader.dismiss()
if(res=="Your Login Success"){
let alert = this.altCtrl.create({
title:"CONGRATS",
subTitle:(res),
buttons: ['OK']
});
alert.present().then(()=>
this.navCtrl.push(NextPage));
}
else{
let alert = this.altCtrl.create({
title:"ERROR",
subTitle:"Your Login Username or Password is invalid",
buttons: ['OK']
});
alert.present();
}
},(err) => {
});
});
}
I expect if the username or password is wrong it should show alert "username or password incorrect". in else it will push to the next page with "your login success".
You should do something like this:
in your Login.ts
let loginObject = {
username: userInputValueFromUsername
password: userInputValueFromPassword
}
this.headers = {'Content-Type':'application/json'}; // set Headers for the Request
this.http.post('https://somew-url.com/api/login', JSON.stringify(loginObject), {headers: this.headers})
.subscribe(data => {
console.log(data);
if (data.success == true) {
//push to new Page
}
else{
// Show Error
}
});

Backand: Sign user in immediately after registering?

Having trouble doing this - is it even possible?
Sign-up Email Verification is off, and I'm doing this in the config:
BackandProvider.setAppName( 'test' );
BackandProvider.runSigninAfterSignup( true );
// ... tokens, etc.
Getting this back in the response after hitting the /1/user/signup endpoint:
data : {
currentStatus : 1,
listOfPossibleStatus : [...],
message : "The user is ready to sign in",
token : "...",
username : "tester#test.com"
}
Do I need to make another API call? Can't find where and with which params.
Yes, you must make another API call to get token after sign up. If you use the Backand SDK by default it makes the second call.
$scope.signup = function (form) {
return Backand.signup(form.firstName, form.lastName,
form.username, form.password,
form.password,
{company: form.company})
.then(function (response) {
$scope.getUserDetails();
return response;
});
};
If you lool at the SDK code, this is what happens there:
self.signup = function (firstName, lastName, email, password, confirmPassword, parameters) {
return http({
method: 'POST',
url: config.apiUrl + urls.signup,
headers: {
'SignUpToken': config.signUpToken
},
data: {
firstName: firstName,
lastName: lastName,
email: email,
password: password,
confirmPassword: confirmPassword,
parameters: parameters
}
}).then(function (response) {
$rootScope.$broadcast(EVENTS.SIGNUP);
if (config.runSigninAfterSignup
&& response.data.currentStatus === 1) {
return self.signin(email, password);
}
return response;
})
};