Angular 6 error doesn't fire - angular6

I am learning angular and for my example using Firebase createUserWithEmailAndPassword for sign-up. This returns a promise which i have changed to observable using from.
In firebase minimum password length is 6 characters. When i provide 5 characters, in the console i see the error message but in my sign-up event, success message shows rather than error. What am i missing here?
AuthService
import * as firebase from 'firebase';
import { throwError, from } from 'rxjs';
export class AuthService{
//user sign up, its a promise so listen for errors and log
signUpUser(email: string, password: string){
//return an observable using from
return from(
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(
(authData) => {
//good
console.log("User created successfully with payload-", authData);
return authData;
}
)
.catch(
(error) => {
//error
console.log(error);
return throwError(error);;
}
)
);
}
}
Sign-up component
onSignup(form: NgForm){
const email = form.value.email;
const password = form.value.password;
this.authService.signUpUser(email, password).subscribe(
(authData) => {
alert("Signup successful");
this.router.navigate(['/sign-in']);
},
(error) => {
alert(error.message);
}
);
}
Also i am using then in the authService method. How can i do .pipe(map(return authData.json()))?
Update 1:
Following helped and i am getting my error, on successful registration i am getting redirected to the sign-in view.
Convert promise to observable
AuthService
import { from } from 'rxjs';
signUpUserNew(email: string, password: string){
var subscription = from(firebase.auth().createUserWithEmailAndPassword(email, password));
return subscription;
}
Sign-up Component
//property to hold result of sign-up error
error = '';
onSignup(form: NgForm){
const email = form.value.email;
const password = form.value.password;
//this.authService.signUpUser(email, password);
this.authService.signUpUserNew(email, password)
.subscribe(
(firebaseUser) => {
console.log(firebaseUser);
this.router.navigate(['/sign-in']);
},
(error) => {
this.error = error.message;
}
);
}
View
<h2>Register</h2>
<div class="row">
<div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">
<form (ngSubmit)="onSignup(f)" #f="ngForm">
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" ngModel class="form-control" #email="ngModel" required email>
<span class="help-block" *ngIf="!email.valid && email.touched">Please enter a valid email!</span>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" ngModel class="form-control" #password="ngModel" required minlength="6">
<span class="help-block" *ngIf="!password.valid && password.touched && !password.errors?.minlength">Please enter a valid password!</span>
<span class="help-block" *ngIf="!password.valid && password.touched && password.errors?.minlength">Password must be at least 6 characters long</span>
</div>
<p class="error" *ngIf="error">{{ error }}</p>
<button class="btn btn-primary" type="submit" [disabled]="!f.valid">Sign Up</button>
</form>
</div>
</div>
Result
Pending
Now i still need help implementing pipe and map operators.
I am getting the following error on .json:
[ts] Property 'json' does not exists on type 'UserCredential'
onSignup(form: NgForm){
const email = form.value.email;
const password = form.value.password;
//this.authService.signUpUser(email, password);
this.authService.signUpUserNew(email, password)
.pipe(
map(
(firebaseUser) => {
return firebaseUser.json();
}
)
)
.subscribe(
(firebaseUser) => {
console.log(firebaseUser);
this.router.navigate(['/sign-in']);
},
(error) => {
this.error = error.message;
}
);
}

Firstly, I guess you should call fromPromise instead of from, so try the following:
import 'rxjs/add/observable/fromPromise';
import { Observable } from "rxjs/Observable";
signUpUser(email: string, password: string){
//return an observable using fromPromise
const obs$ = fromPromise(
firebase.auth().createUserWithEmailAndPassword(email, password)
);
// you can call .pipe() here, and it will return an observable
return obs$.pipe(
map(x => console.log('PUT YOUR MAP FUNCTION HERE.')),
filter(x => console.log('Call filter() if you want'))
);
}
And you can subscribe to this observable
const subscription = this.authService.signUpUser(email, password).subscribe(
(firebaseUser) => {
console.log('firebase user: ', firebaseUser);
alert("Signup successful");
this.router.navigate(['/sign-in']);
},
(error) => {
alert(error.message);
}
);

Related

React: Error-Message does not show up, while others do?

I have this simple Login-Form, in which I want to display an Error-Message, which contains Login tries (3 tries possible). Somehow, my one errormessage (loginTries) is not being displayed. Why?
My form is running the method handleSubmitAndStartTimer() when I submit it. You can find more comments and details below:
export const Login = () => {
const [errorMessages, setErrorMessages] = useState({});
const [loginFailCounter, setLoginFailCounter] = useState(2);
const [firstTimeSubmitted, setFirstTimeSubmitted] = useState(false);
const mockUserData = [
{
username: "user1",
password: "pass1",
istGesperrt: false,
},
];
const handleSubmitAndStartTimer = (event) => {
setFirstTimeSubmitted(true);
event.preventDefault();
var { benutzername, passwort } = document.forms[0];
const userData = mockUserDaten.find(
(user) => user.username === benutzername.value
);
// Compare user info
if (userData) {
if (!userData.istGesperrt) {
if (userData.password !== passwort.value) {
setLoginFailCounter(loginFailCounter - 1);
// THIS DOESNT WORK!
setErrorMessages({ name: "loginTries", message: errors.loginTries, });
// ALL THESE ERROR MESSAGES WORK!
// Invalid password
setErrorMessages({ name: "passwort", message: errors.passwort });
} else {
// Username not found
setErrorMessages({
name: "benutzername",
message: errors.benutzername,
});
}
} else {
setErrorMessages({
name: "userGesperrt",
message: errors.userGesperrt,
});
}
}
};
// This method is called to display to correct message
const renderErrorMessage = (name) =>
name === errorMessages.name && (
<div className="error">{errorMessages.message}</div>
);
const errors = {
benutzername: "invalid username",
passwort: "invalid password",
loginTries: loginFailCounter + " Tries possible!",
userGesperrt: "",
};
const renderForm = (
<div className="form">
<form onSubmit={handleSubmitAndStartTimer}>
<div className="input-container">
<label for="benutzername">Benutzername</label>
<input type="text" id="benutzername" name="benutzername" required />
{renderErrorMessage("benutzername")}
</div>
<div className="input-container">
<label for="passwort">Passwort</label>
<input type="passwort" id="passwort" name="passwort" required />
{renderErrorMessage("passwort")}
</div>
<div className="button-container">
<input type="submit" value="Log in" />
</div>
{renderErrorMessage("userGesperrt")}
// THIS MESSAGE ISNT BEING SHOWN!
{renderErrorMessage("loginTries")}
</form>
</div>
);
return (
<div className="app">
<div className="login-form">
<div className="title">Sign In</div>
{isSubmitted ? <div>User is successfully logged in</div> : renderForm}
</div>
</div>
);
};
export default Login;

Netflify Serverless Function JSON parse error Sendgrid API

My contact form is not sending the frontend user to my thank you page neither is it sending any information to me via the Sendgrid APi. The issue comes from the fact that I'm not sure how to turn the JSON object into a string and then straight back to an Object..... Or as you can see I have a hard time even framing my question. The goal would be to send the information to my email account using Sendgrid API.
The form is live here:
https://www.metsanotus.fi/yhteydenotto
The code is based 99% off these two tutorials:
https://oliverschmidt.dev/blog/adding-a-contact-form-to-a-static-site-with-netlify-functions/
https://dev.to/char_bone/using-netlify-lambda-functions-to-send-emails-from-a-gatsbyjs-site-3pnb
The code for the contact-page:
https://gist.github.com/otsolap/f05cd4e3a1a08794f61a6d5730abc695
import React, { useState } from "react";
import { graphql } from "gatsby"
import { RiSendPlane2Line } from "react-icons/ri";
import Layout from "../components/layout"
import SEO from "../components/seo"
export const pageQuery = graphql`
query ContactQuery($id: String!){
markdownRemark(id: { eq: $id }) {
id
html
excerpt(pruneLength: 140)
frontmatter {
title
}
}
site {
siteMetadata {
title
}
}
}
`
const Contact = ({ data }) => {
const { markdownRemark, site } = data // data.markdownRemark holds your post data
const { frontmatter, html } = markdownRemark
// input type hidden on netlifytä varten, jotta netlify tietää mikä lomake kyseessä.
// contact on meidän lomake, niin kaikki viestit löytyy contact-lomakkeen alta.
// honeypot=bot-field on botteja varten.
// p hidden pitää kohdan piilossa, mutta console.logilla sen löytää. ;-)
const [formState, setFormState] = useState({
name: '',
email: '',
phone: '',
subject: '',
message: '',
})
const handleChange = (e) => {
setFormState({
...formState,
[e.target.name]: e.target.value,
});
}
const handleSendEmail = async (event) => {
event.preventDefault();
try {
const response = await fetch("/.netlify/functions/contact-form-email", {
method: "POST",
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formState),
})
if (!response.ok) {
//EI 200 response
return
}
//all OK
} catch (event) {
//error
}
}
return (
<Layout className="contact-page">
<SEO
title={frontmatter.title}
description={frontmatter.title + " " + site.siteMetadata.title}
/>
<div className="wrapper">
<h1>{frontmatter.title}</h1>
<div className="description" dangerouslySetInnerHTML={{ __html: html }} />
<form className="contact-form"
action="/kiitos"
name="contact"
method="POST"
data-netlify="true"
value="contact"
data-netlify-honeypot="bot-field"
onSubmit={handleSendEmail}
>
<input type="hidden" name="form-name" value="contact" />
<p hidden><input name="bot-field" /></p>
<p>
<label><input
required
placeholder="Nimi *"
type="text"
name="name"
onChange={handleChange}
/>
</label>
</p>
<p>
<label><input required
placeholder="Sähköposti *"
type="email"
name="email"
onChange={handleChange}
/>
</label>
</p>
<p>
<label><input required
placeholder="Puhelin *"
type="number"
name="phone"
onChange={handleChange}
/>
</label>
</p>
<p>
<label><input placeholder="Aihe"
type="text"
name="subject"
onChange={handleChange}
/>
</label>
</p>
<p>
<label><textarea
placeholder="Viesti"
name="message"
onChange={handleChange}
></textarea></label>
</p>
<p className="text-align-center">
<button className="button"
type="submit">
Lähetä<span className="icon -right"><RiSendPlane2Line />
</span>
</button>
</p>
</form>
</div>
</Layout>
)
}
export default Contact
The code for the serverless function:
https://gist.github.com/otsolap/e157b136aee040281f20ba87131014eb
require('dotenv').config();
const sgMail = require('#sendgrid/mail')
const {
SENDGRID_API_KEY,
METSAN_OTUS_NAME,
METSAN_OTUS_ADDRESS }
= process.env
sgMail.setApiKey(SENDGRID_API_KEY)
exports.handler = async (event, context, callback) => {
const payload = JSON.parse(event.body)
const { email, subject, message } = payload
const msg = {
to: METSAN_OTUS_ADDRESS,
name: METSAN_OTUS_NAME,
from: email,
subject: subject ? subject : 'Yhteydenotto lomakkeesta',
text: message,
};
try {
await sgMail.send(msg)
return {
statusCode: 200,
body: "Viesti lähetetty"
}
} catch (e) {
return {
body: e.message,
statusCode: 500,
}
}
};
When I keep the JSON.parse(body.event) this is the error it displays:
https://gist.github.com/otsolap/79830f6cf1e9b247c63c1f3f49c5286b
SyntaxError: Unexpected token u in JSON at position 0
If I change the line 13 of serverless-function.js from JSON.parse(event.body) to (for example) JSON.stringify(event.body) the error becomes this:
TypeError: Cannot destructure property 'email' of 'payload' as it is undefined.
So I guess my question is how should I formulate my serverless function so that the React object from UseState can become readable for my function?

Is there anyway to authenticate the user type(user and Supplier) without any token in react and go with different page when I fetch the response api?

is it anyway or solution that can authenticate the result in response JSON without any token authentication? My project have two type of user (user=1 and supplier=2). I need both of this user has different pages when they login to my system. The response JSON are as below:
This user is normal user will go to user page, while other user with user type of 2 will go to supplier page.
Here is my code:
login(){
if(this.state.loginEmail && this.state.loginPassword){
PostData('api/users/login', this.state).then ((result) => {
let responseJSON = result;
console.log(responseJSON)
if(responseJSON.user){
sessionStorage.setItem('user', responseJSON);
// console.log("Home Page")
this.setState({redirect: true});
}else{
console.log("Login Error")
alert("wrong user credential")
}
});
}
}
On the render component, when user login successfully I use redirect to go to Home page"/home":
render(){
if(this.state.redirect){
return (<Redirect to={{
pathname: '/home',
state: { loginEmail : this.state.loginEmail }}}/>)
}
if(sessionStorage.getItem("user")){
return (<Redirect to ={'/home'}/>)
}
return (
<div className="login-background">
<div className = " login-form">
<h1>Login</h1>
<div className = "txtb">
<input type="text" name="loginEmail" placeholder= "email" onChange={this.onChange}/>
</div>
<div className = "txtb">
<input type="password" name="loginPassword" placeholder="password" onChange={this.onChange}/>
</div>
<input type="submit" value="Login" className="logbtn" onClick={this.login}/>
<div className = "bottom-text">
Dont have account? Sign up
</div>
</div>
</div>
);
}
What I want is when userType is equal to 2, they will go to supplier page "/supplier".
Assuming that you have already connected your component with react-router, this is how you can redirect your user to the respective paths based on the userType.
login(){
if(this.state.loginEmail && this.state.loginPassword){
PostData('api/users/login', this.state).then ((result) => {
const { data: { user_info: { userType } } } = result;
if (userType === 1) {
history.push('/home');
} else if (userType === 2) {
history.push('/supplier')
}
});
}
}

How to login validation using my api in React Js

React JS
I'm new to react js
In my api there is username and password. If the user login, have to validate from my json value
handleSubmit(e) {
fetch('https://randomuser.me/api?results=1')
.then((response) => {
return response.json()
.then((json) => {
if (response.ok) {
return Promise.resolve(json)
}
return Promise.reject(json)
})
})
alert(json) not working to check the result.
How can i fetch the username and password in the response?
And how to take this next page if the user was logged in successfully ?
My full Code
App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
const ReactCSSTG = CSSTransitionGroup;
class App extends Component {
constructor(props) {
super(props);
this.state = {
isVisible: true
}
// Bindings
this.handleSubmit = this.handleSubmit.bind(this);
this.handleRemount = this.handleRemount.bind(this);
}
handleSubmit(e) {
alert("dsa");
fetch('https://randomuser.me/api?results=1')
.then((response) => {
return response.json()
.then((json) => {
if (response.ok) {
return Promise.resolve(json)
}
return Promise.reject(json)
})
})
}
handleRemount(e) {
this.setState({
isVisible: true
}, function () {
console.log(this.state.isVisible)
});
e.preventDefault();
}
render() {
// const for React CSS transition declaration
let component = this.state.isVisible ? <Modal onSubmit={this.handleSubmit} key='modal' /> : <ModalBack onClick={this.handleRemount} key='bringitback' />;
return <ReactCSSTG transitionName="animation" transitionAppear={true} transitionAppearTimeout={500} transitionEnterTimeout={500} transitionLeaveTimeout={300}>
{component}
</ReactCSSTG>
}
}
// Modal
class Modal extends React.Component {
render() {
return <div className='Modal'>
<Logo />
<form onSubmit={this.props.onSubmit}>
<Input type='text' name='username' placeholder='username' />
<Input type='password' name='password' placeholder='password' />
<button> Sign In</button>
</form>
<a href='#'>Lost your password ?</a>
</div>
}
}
// Generic input field
class Input extends React.Component {
render() {
return <div className='Input'>
<input type={this.props.type} name={this.props.name} placeholder={this.props.placeholder} required />
<label htmlFor={this.props.name}></label>
</div>
}
}
// Fake logo
class Logo extends React.Component {
render() {
return <div className="logo">
<i><img src={logo} className="App-logo" alt="logo" /></i>
<span> Test </span>
</div>
}
}
// Button to brind the modal back
class ModalBack extends React.Component {
render() {
return (
<button className="bringitback" onClick={this.props.onClick} key={this.props.className}>Back to login page!</button>
);
}
}
export default App;
Thanks in Advance!
If you just want to catch data for now this will do the trick
fetch('https://randomuser.me/api?results=1')
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(JSON.stringify(myJson));
});
fetch('https://randomuser.me/api?results=1')
.then((response) => {
// check for status code from service if success
// set response in state such as login success
this.route.navigate(['/']);
})
.catch(error =>{
console.log(error);
});
})
Taking user to next page. Use react router for achieving this.
Step 1: Wrap your <App /> inside <BrowserRouter />
Now validate response if username/password are correct using service call.
Then this.route.navigate(['/']);
This will navigate user to home page of app after successful login.
Heres What I did, keep in mind I set up my backend with express/node.
I used Axios to fetch from my api.
onSubmit = (e) => {
e.preventDefault();
axios.get('API_PATH')
.then(res => {
const user = res.data[0].username;
const password = res.data[0].password;
const username = this.state.username;
const passwordEntered = this.state.password;
if(username === '' && passwordEntered === ''){
document.getElementById('status').innerHTML = '<p>Please Enter A Valid Username and Password</p>';
}else if(user === username && passwordEntered === password){
document.getElementById('status').innerHTML = '';
console.log(user, password)
}else{
document.getElementById('status').innerHTML = '<p>Please Enter A Valid Username and Password</p>';
}
})
.catch(error => {
console.log(error);
});
}
Here is the form I used.
<Form
>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>Username</Form.Label>
<Form.Control
type="text"
name="username"
id="username"
value={this.state.value}
onChange={this.handleChange}
>
</Form.Control>
</Form.Group>
<Form.Group as={Col}>
<Form.Label>Password</Form.Label>
<Form.Control
type="text"
id="password"
name="password"
value={this.state.value}
onChange={this.handleChange}
/>
</Form.Group>
</Form.Row>
<Button className="btn btn-sm btn-light" onClick={this.onSubmit}>
<i style={redColor} className="fas fa-sign-in-alt"></i> Login
</Button>
</Form>

Authenticating users with JWT in Angular 4 + Node + MySQL

I'm trying to do an auth login to an API request using JWT but I'm not being able to do it using my own database.
I'm using MySQL and, if you could, please provide me a code to do the response.
Until now I have only checked that if the email matches the one below ('mymail#domain), the user is authenticated.
I would like to know the best way to do a request to my MySQL database and compare the user with the one entered in the input, that all using JWT.
I'm learning so please, if you could explain the approach, I appreciate.
The frontend I'm using Angular 4, and this is the code:
login.component.html
<form class="form-signin" #f="ngForm" (ngSubmit)="signIn(f.value)">
<h2 class="form-signin-heading">Please sign in</h2>
<div *ngIf="invalidLogin" class="alert alert-danger">Invalid username and/or password.</div>
<label for="inputEmail" class="sr-only">Email address</label>
<input type="email" id="inputEmail" name="email" ngModel class="form-control" placeholder="Email address" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" id="inputPassword" name="password" ngModel class="form-control" placeholder="Password" required>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
login.component.ts
import {Component, Inject} from '#angular/core';
import { Router } from "#angular/router";
import { AuthService } from '../../auth/auth.service';
...
email: string;
senha:string;
invalidLogin: boolean;
constructor(private router: Router,
private authService: AuthService) {}
signIn(credentials) {
this.authService.login(credentials)
.subscribe(result => {
if (result){
this.router.navigate(['/']);
}
else {
this.invalidLogin = true;
}
});
}
auth.service.ts
import { Http } from '#angular/http';
import { Injectable } from '#angular/core';
import { tokenNotExpired, JwtHelper } from 'angular2-jwt';
import 'rxjs/add/operator/map';
...
currentUser: any;
constructor(private http: Http) {
let token = localStorage.getItem('token');
if (token) {
let jwt = new JwtHelper();
this.currentUser = jwt.decodeToken(token);
}
}
login(credentials) {
return this.http.post('/api/user/authenticate', credentials)
.map(response => {
let result = response.json();
if (result && result.token) {
localStorage.setItem('token', result.token);
let jwt = new JwtHelper();
this.currentUser = jwt.decodeToken(localStorage.getItem('token'));
return true;
}
else return false;
});
}
This is my code in app.js (API in NodeJS)
const express = require('express');
const bodyParser = require('body-parser');
var jwt = require('jsonwebtoken');
var bcrypt = require('bcrypt');
...
app.post('/api/user/authenticate',function(req,res){
let body = req.body;
if (body.email === 'mymail#domain.com' && body.password === '1234') {
console.log('correct');
} else {
console.log('incorrect');
}
});
This is the endpoint where all my users are located:
/clientes
and it's shown like this:
{"ID":14,"Name":"Robert","Email":"robert#nest.com","Password":"14564964"}
Thank you!