I'm trying to add next-auth authentication with credentials(it's my first time and the source I'm using for following is using version 3 as I know, therefore there is a lot of difference and I couldn't find the right solution for days). Basically I have got form of registration and log-in form, and as a backend server I'm using mongodb. the registration form works normally, user is able to create account, but the log-in form doesn't seem to be working and in console when user sends request for logging in comes up error: {error: 'client.db.collection is not a function', status: 401, ok: false, url: null}.
This is pages/api/[...nextauth].js file.
import { verifyPassword } from "#/lib/auth";
import connectToDatabase from "#/lib/db";
import NextAuth from "next-auth/next";
import CredentialsProvider from "next-auth/providers/credentials";
export default NextAuth({
session: {
strategy: "jwt",
},
providers: [
CredentialsProvider({
async authorize(credentials, req) {
const client = await connectToDatabase();
const userCollection = client.db.collection("users");
const user = await userCollection.findOne({ email: credentials.email });
if (!user) {
client.close();
throw new Error("No user found!");
}
const isValid = verifyPassword(credentials.password, user.password);
if (!isValid) {
client.close();
throw new Error("Could not log you in.");
}
client.close();
return { email: user.email };
},
}),
],
});
and this is loginForm.js that should send request to log-in.
import React, { useRef } from "react";
import Link from "next/link";
import { signIn } from "next-auth/react";
const LoginForm = () => {
const emailRef = useRef();
const passwordRef = useRef();
const submitHandler = async (e) => {
e.preventDefault();
const enteredEmail = emailRef.current.value;
const enteredPassword = passwordRef.current.value;
try {
const result = await signIn("credentials", {
redirect: false,
email: enteredEmail,
password: enteredPassword,
});
console.log(result);
} catch (error) {
console.log(error.error);
}
};
return (
<div
className="container d-flex justify-content-center align-items-center"
style={{ width: "100%", height: "100vh" }}
>
<div className="col-6-sm">
<form onSubmit={submitHandler}>
<div className="form-outline mb-4">
<input
type="email"
id="form2Example1"
className="form-control"
ref={emailRef}
/>
<label className="form-label" for="form2Example1">
Email address
</label>
</div>
<div className="form-outline mb-4">
<input
type="password"
id="form2Example2"
className="form-control"
ref={passwordRef}
/>
<label className="form-label" for="form2Example2">
Password
</label>
</div>
<button type="submit" className="btn btn-dark m-1">
Sign in
</button>
<Link href="/register" className="btn btn-dark m-1">
Register
</Link>
</form>
</div>
</div>
);
};
export default LoginForm;
Related
Trying to login user via firebase, receiving the following error:
ERROR in src/app/modules/auth/core/_requests.ts:28:59
TS2345: Argument of type 'AuthModel | undefined' is not assignable to parameter of type 'Auth'.
Type 'undefined' is not assignable to type 'Auth'.
26 |
27 | export async function login(email: string, password: string) {
28 | const userCredential = await signInWithEmailAndPassword(auth, email, password);
| ^^^^
29 | const user = userCredential.user;
30 | const token = await user.getIdToken();
31 | return {
login.ts
/* eslint-disable jsx-a11y/anchor-is-valid */
import {useState} from 'react'
import * as Yup from 'yup'
import clsx from 'clsx'
import {Link} from 'react-router-dom'
import {useFormik} from 'formik'
import {getUserByToken, login} from '../core/_requests'
import {toAbsoluteUrl} from '../../../../_metronic/helpers'
import {useAuth} from '../core/Auth'
import { Firestore } from 'firebase/firestore'
import { useNavigate } from 'react-router-dom';
const loginSchema = Yup.object().shape({
email: Yup.string()
.email('Wrong email format')
.min(3, 'Minimum 3 symbols')
.max(50, 'Maximum 50 symbols')
.required('Email is required'),
password: Yup.string()
.min(3, 'Minimum 3 symbols')
.max(50, 'Maximum 50 symbols')
.required('Password is required'),
})
const initialValues = {
email: 'admin#demo.com',
password: 'demo',
}
/*
Formik+YUP+Typescript:
https://jaredpalmer.com/formik/docs/tutorial#getfieldprops
https://medium.com/#maurice.de.beijer/yup-validation-and-typescript-and-formik-6c342578a20e
*/
export function Login() {
const [loading, setLoading] = useState(false)
const {saveAuth, setCurrentUser} = useAuth()
const formik = useFormik({
initialValues,
validationSchema: loginSchema,
onSubmit: async (values, {setStatus, setSubmitting}) => {
setLoading(true)
try {
const auth = await login(values.email, values.password)
saveAuth(auth)
const {data: user} = await getUserByToken(auth.api_token)
setCurrentUser(user)
} catch (error) {
console.error(error)
saveAuth(undefined)
setStatus((error as Error).message)
} finally {
setSubmitting(false)
setLoading(false)
}
},
})
return (
<form
className='form w-100'
onSubmit={formik.handleSubmit}
noValidate
id='kt_login_signin_form'
>
{/* begin::Heading */}
<div className='text-center mb-10'>
<h1 className='text-dark mb-3'>Sign In to Web Construct</h1>
<div className='text-gray-400 fw-bold fs-4'>
New Here?{' '}
<Link to='/auth/registration' className='link-primary fw-bolder'>
Create an Account
</Link>
</div>
</div>
{/* begin::Heading */}
{formik.status ? (
<div className='mb-lg-15 alert alert-danger'>
<div className='alert-text font-weight-bold'>{formik.status}</div>
</div>
) : (
<div className='mb-10 bg-light-info p-8 rounded'>
<div className='text-info'>
Use account <strong>admin#demo.com</strong> and password <strong>demo</strong> to
continue.
</div>
</div>
)}
{/* begin::Form group */}
<div className='fv-row mb-10'>
<label className='form-label fs-6 fw-bolder text-dark'>Email</label>
<input
placeholder='Email'
{...formik.getFieldProps('email')}
className={clsx(
'form-control form-control-lg form-control-solid',
{'is-invalid': formik.touched.email && formik.errors.email},
{
'is-valid': formik.touched.email && !formik.errors.email,
}
)}
type='email'
name='email'
autoComplete='off'
/>
{formik.touched.email && formik.errors.email && (
<div className='fv-plugins-message-container'>
<span role='alert'>{formik.errors.email}</span>
</div>
)}
</div>
{/* end::Form group */}
{/* begin::Form group */}
<div className='fv-row mb-10'>
<div className='d-flex justify-content-between mt-n5'>
<div className='d-flex flex-stack mb-2'>
{/* begin::Label */}
<label className='form-label fw-bolder text-dark fs-6 mb-0'>Password</label>
{/* end::Label */}
{/* begin::Link */}
<Link
to='/auth/forgot-password'
className='link-primary fs-6 fw-bolder'
style={{marginLeft: '5px'}}
>
Forgot Password ?
</Link>
{/* end::Link */}
</div>
</div>
<input
type='password'
autoComplete='off'
{...formik.getFieldProps('password')}
className={clsx(
'form-control form-control-lg form-control-solid',
{
'is-invalid': formik.touched.password && formik.errors.password,
},
{
'is-valid': formik.touched.password && !formik.errors.password,
}
)}
/>
{formik.touched.password && formik.errors.password && (
<div className='fv-plugins-message-container'>
<div className='fv-help-block'>
<span role='alert'>{formik.errors.password}</span>
</div>
</div>
)}
</div>
{/* end::Form group */}
{/* begin::Action */}
<div className='text-center'>
<button
type='submit'
id='kt_sign_in_submit'
className='btn btn-lg btn-primary w-100 mb-5 '
disabled={formik.isSubmitting || !formik.isValid}
>
{!loading && <span className='indicator-label'>Continue</span>}
{loading && (
<span className='indicator-progress' style={{display: 'block'}}>
Please wait...
<span className='spinner-border spinner-border-sm align-middle ms-2'></span>
</span>
)}
</button>
{/* begin::Separator */}
<div className='text-center text-muted text-uppercase fw-bolder mb-5'>or</div>
{/* end::Separator */}
{/* begin::Google link */}
<a className='btn btn-flex flex-center btn-light btn-lg w-100 mb-5'>
<img
alt='Logo'
src={toAbsoluteUrl('/media/svg/brand-logos/google-icon.svg')}
className='h-20px me-3'
/>
Continue with Google
</a>
{/* end::Google link */}
{/* begin::Google link */}
<a href='#' className='btn btn-flex flex-center btn-light btn-lg w-100 mb-5'>
<img
alt='Logo'
src={toAbsoluteUrl('/media/svg/brand-logos/facebook-4.svg')}
className='h-20px me-3'
/>
Continue with Facebook
</a>
{/* end::Google link */}
{/* begin::Google link */}
<a href='#' className='btn btn-flex flex-center btn-light btn-lg w-100'>
<img
alt='Logo'
src={toAbsoluteUrl('/media/svg/brand-logos/apple-black.svg')}
className='h-20px me-3'
/>
Continue with Apple
</a>
{/* end::Google link */}
</div>
{/* end::Action */}
</form>
)
}
requests.ts
import axios from 'axios'
import {AuthModel, UserModel} from './_models'
import {auth} from "../../../../firebase.js";
import {
Auth,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut,
onAuthStateChanged,
} from 'firebase/auth';
const API_URL = process.env.REACT_APP_API_URL
export const GET_USER_BY_ACCESSTOKEN_URL = `${API_URL}/verify_token`
export const LOGIN_URL = `${API_URL}/login`
export const REGISTER_URL = `${API_URL}/register`
export const REQUEST_PASSWORD_URL = `${API_URL}/forgot_password`
// Server should return AuthModel - OLD SIGN IN
// export function login(email: string, password: string) {
// return axios.post<AuthModel>(LOGIN_URL, {
// email,
// password,
// })
// }
export async function login(email: string, password: string) {
const userCredential = await signInWithEmailAndPassword(auth, email, password);
const user = userCredential.user;
const token = await user.getIdToken();
return {
api_token: token,
email: user.email,
// add any other user data you need to the AuthModel object
};
}
// Server should return AuthModel
export function register(
email: string,
firstname: string,
lastname: string,
password: string,
password_confirmation: string
) {
return axios.post(REGISTER_URL, {
email,
first_name: firstname,
last_name: lastname,
password,
password_confirmation,
})
}
// Server should return object => { result: boolean } (Is Email in DB)
export function requestPassword(email: string) {
return axios.post<{result: boolean}>(REQUEST_PASSWORD_URL, {
email,
})
}
export function getUserByToken(token: string) {
return axios.post<UserModel>(GET_USER_BY_ACCESSTOKEN_URL, {
api_token: token,
})
}
firebase.js
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth } from "./app/modules/auth";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: "AIzaSyAwRC9aw8fFfTkm-hl7pjR5_CTB2leohOI",
authDomain: "web-construct-app.firebaseapp.com",
projectId: "web-construct-app",
storageBucket: "web-construct-app.appspot.com",
messagingSenderId: "576412080434",
appId: "1:576412080434:web:fbdd24284ee1d316e65f2b",
measurementId: "G-JZJCSM78J4"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app)
export default app
auth.tsx
import {
FC,
useState,
useEffect,
createContext,
useContext,
useRef,
Dispatch,
SetStateAction,
} from 'react'
import {LayoutSplashScreen} from '../../../../_metronic/layout/core'
import {AuthModel, UserModel} from './_models'
import * as authHelper from './AuthHelpers'
import {getUserByToken} from './_requests'
import {WithChildren} from '../../../../_metronic/helpers'
type AuthContextProps = {
auth: AuthModel | undefined
saveAuth: (auth: AuthModel | undefined) => void
currentUser: UserModel | undefined
setCurrentUser: Dispatch<SetStateAction<UserModel | undefined>>
logout: () => void
}
const initAuthContextPropsState = {
auth: authHelper.getAuth(),
saveAuth: () => {},
currentUser: undefined,
setCurrentUser: () => {},
logout: () => {},
}
const AuthContext = createContext<AuthContextProps>(initAuthContextPropsState)
const useAuth = () => {
return useContext(AuthContext)
}
const AuthProvider: FC<WithChildren> = ({children}) => {
const [auth, setAuth] = useState<AuthModel | undefined>(authHelper.getAuth())
const [currentUser, setCurrentUser] = useState<UserModel | undefined>()
const saveAuth = (auth: AuthModel | undefined) => {
setAuth(auth)
if (auth) {
authHelper.setAuth(auth)
} else {
authHelper.removeAuth()
}
}
const logout = () => {
saveAuth(undefined)
setCurrentUser(undefined)
}
return (
<AuthContext.Provider value={{auth, saveAuth, currentUser, setCurrentUser, logout}}>
{children}
</AuthContext.Provider>
)
}
const AuthInit: FC<WithChildren> = ({children}) => {
const {auth, logout, setCurrentUser} = useAuth()
const didRequest = useRef(false)
const [showSplashScreen, setShowSplashScreen] = useState(true)
// We should request user by authToken (IN OUR EXAMPLE IT'S API_TOKEN) before rendering the application
useEffect(() => {
const requestUser = async (apiToken: string) => {
try {
if (!didRequest.current) {
const {data} = await getUserByToken(apiToken)
if (data) {
setCurrentUser(data)
}
}
} catch (error) {
console.error(error)
if (!didRequest.current) {
logout()
}
} finally {
setShowSplashScreen(false)
}
return () => (didRequest.current = true)
}
if (auth && auth.api_token) {
requestUser(auth.api_token)
} else {
logout()
setShowSplashScreen(false)
}
// eslint-disable-next-line
}, [])
return showSplashScreen ? <LayoutSplashScreen /> : <>{children}</>
}
export {AuthProvider, AuthInit, useAuth}
Tried passing savAuth as null, but no luck.
I am new to react development. I am using redux to update my product. I had succeeded in updating the product from postman but I couldn't update from the admin panel. I think there is an issue in the front end as API is tested using postman and the backend is working. Kindly help me.
My Product component
import { Link } from "react-router-dom";
import "./Product.css";
import { useLocation } from "react-router-dom";
import axios from "axios";
import { Publish } from '#mui/icons-material';
import { useSelector } from "react-redux";
import { updateProduct } from "../../Redux/apiCalls";
import { useDispatch } from "react-redux";
import { useState } from "react";
const Product = () => {
const location=useLocation();
const productId=location.pathname.split("/")[2];
const product=useSelector(state=>state.product.products.find(product=>product._id===productId))
const dispatch=useDispatch();
console.log(productId);
// const [title, setTitle]=useState("");
// const [desc, setDesc]=useState("");
// const [price, setPrice]=useState("");
// const [inStock, setInStock]=useState("");
const [inputs, setInputs]=useState({})
const handleChange=(e)=>{
setInputs((prev) => {
return { ...prev, [e.target.name]: e.target.value };
});
}
console.log(inputs);
const handleUpdate=async()=>{
await updateProduct(productId, inputs , dispatch)
// await axios.put('http://localhost:5000/api/products/`$productId`', inputs, productId)
// .then(response=>console.log(response.data))
}
return ( <>
<div className="product">
<div className="productTitleContainer">
<h1 className="productTitle">Product</h1>
<Link to="/newproduct">
<button className="productAddButton">Create</button>
</Link>
</div>
<div className="productTop">
<div className="productTopRight">
<div className="productInfoTop">
{/* <img src={product.img} alt="" className="productInfoImg" /> */}
<span className="productName">Product Name</span>
</div>
<div className="productInfoBottom">
<div className="productInfoItem">
<span className="productInfoKey">id:</span>
<span className="productInfoValue">{product._id}</span>
</div>
<div className="productInfoItem">
<span className="productInfoKey">sales:</span>
<span className="productInfoValue">5123</span>
</div>
<div className="productInfoItem">
<span className="productInfoKey">Price</span>
<span className="productInfoValue">{product.price}</span>
</div>
<div className="productInfoItem">
<span className="productInfoKey">in stock:</span>
<span className="productInfoValue">{product.inStock}</span>
</div>
</div>
</div>
</div>
<div className="productBottom">
<form className="productForm">
<div className="productFormLeft">
<label>Product Name</label>
<input type="text" placeholder={product.title} name="title" onChange={handleChange} />
<label>Product Description</label>
<input type="text" placeholder={product.desc} name="desc" onChange={handleChange} />
<label>Product Price</label>
<input type="text" placeholder={product.price} name="price" onChange={handleChange}/>
<label>In Stock</label>
<select name="inStock" id="idStock"
onChange={handleChange}
>
<option value="true">Yes</option>
<option value="false">No</option>
</select>
</div>
<div className="productFormRight">
<div className="productUpload">
<img src={product.img} alt="" className="productUploadImg"
/>
<label for="file">
<Publish/>
</label>
<input type="file" id="file" style={{display:"none"}} />
</div>
<button className="productButton" onClick={(e)=>handleUpdate(e.preventDefault())}>Update</button>
</div>
</form>
</div>
</div>
</> );
}
export default Product;
My Update component in Redux
export const updateProduct = async (id, product, dispatch) => {
dispatch(updateProductStart());
try {
const res = await userRequest.put(`/products/${id}`);
dispatch(updateProductSuccess({ id, product }));
} catch (err) {
dispatch(updateProductFailure());
}
};
updateProductStart: (state) => {
state.isFetching = true;
state.error = false;
},
updateProductSuccess: (state, action) => {
state.isFetching = false;
state.products[
state.products.findIndex((item) => item._id === action.payload.id)
] = action.payload.product;
},
updateProductFailure: (state) => {
state.isFetching = false;
state.error = true;
},
My API
import { ConstructionOutlined } from "#mui/icons-material";
import axios from "axios";
const BASE_URL = "http://localhost:5000/api/";
const user = JSON.parse(localStorage.getItem("persist:root"))?.user;
const currentUser = user && JSON.parse(user).currentUser;
const TOKEN = currentUser?.accessToken;
// const TOKEN = JSON.parse(JSON.parse(localStorage.getItem("persist:root")).user).currentUser.accessToken;
export const publicRequest = axios.create({
baseURL: BASE_URL,
});
export const userRequest = axios.create({
baseURL: BASE_URL,
headers: { token: `Bearer ${TOKEN}` },
});
My routes
router.put("/:id", verifyTokenAndAdmin, async (req, res) => {
try {
const updatedProduct = await Product.findByIdAndUpdate(
req.params.id,
{
$set: req.body,
},
{ new: true }
);
res.status(200).json(updatedProduct)
} catch (err) {
console.log("Can't update")
}
});
Model
const mongoose = require("mongoose");
const ProductSchema = new mongoose.Schema(
{
title: { type: String, required: true, unique: true },
desc: { type: String, required: true },
img: { type: String},
categories: { type: Array },
size: { type: Array },
color: { type: Array },
price: { type: Number, required: true },
inStock: { type: Boolean, default: true },
},
{ timestamps: true }
);
module.exports = mongoose.model("Product", ProductSchema);
Browsers won't allow cross origin requests if backend doesn't send response with header
Access-Control-Allow-Origin: <current domain name>
.
So at backend we need to send response with header Access-Control-Allow-Origin: localhost:3000
-> In express project:
Run
npm install cors
Change express initialization like this
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
This would add a header Access-Control-Allow-Origin: * to each response handled. This header says allow requests from browser within any website
Check more at
https://expressjs.com/en/resources/middleware/cors.html
https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
I've been trying to show the error if user's email and password doesn't match. But can't figure out what I've been doing wrong. When I login with the wrong password it takes me straight to the home page. But what I am trying to do is: if password doesn't match then it won't take me anywhere.
import React, { useEffect, useState } from 'react';
import { Button, Form } from 'react-bootstrap';
import { useLocation, useNavigate } from 'react-router-dom';
import { useSignInWithGoogle, useSignInWithEmailAndPassword, useSendPasswordResetEmail } from
'react-firebase-hooks/auth';
import { FcGoogle } from 'react-icons/fc';
import auth from '../../firebase.init';
import './Login.css';
import LoadingSpinner from '../Loadingspinner/LoadingSpinner';
import toast from 'react-hot-toast';
import axios from 'axios';
const Login = () => {
const location = useLocation();
const navigate = useNavigate();
// let the user go where he came from if he logged in
const from = location.state?.from?.pathname || "/";
// handle google sign in
const [signInWithGoogle, googleUser, googleLoading, googleError] = useSignInWithGoogle(auth);
useEffect(() => {
if (googleUser) {
// console.log(googleUser.user);
navigate(from, { replace: true });
};
}, [navigate, googleUser, from]);
if (googleLoading) {
<LoadingSpinner></LoadingSpinner>
};
// handle email sign in
const [
signInWithEmailAndPassword,
emailUser,
emailLoading,
emailError,
] = useSignInWithEmailAndPassword(auth);
useEffect(() => {
if (emailUser) {
// navigate(from, { replace: true });
}
}, [emailUser, navigate, from]);
// if (emailError) {
// console.log(emailError.message)
// };
/* if (emailLoading) {
<LoadingSpinner></LoadingSpinner>
}; */
// get user infos
const [userInfo, setUserInfo] = useState({
email: "",
password: "",
});
// set errors
const [errors, setErrors] = useState({
email: "",
password: "",
others: ""
});
// send password reset email
const [sendPasswordResetEmail, sending, error] = useSendPasswordResetEmail(
auth
);
// handle password reset mail
const handleResetPass = async () => {
if (userInfo.email) {
await sendPasswordResetEmail(userInfo.email);
toast.success('Reset email has been sent.')
}
else {
toast.error('Please try again')
}
}
// get email
const handleEmailChange = e => {
const emailRegex = /^[^\s#]+#[^\s#]+\.[^\s#]+$/;
if (emailRegex.test(e.target.value)) {
setUserInfo({ ...userInfo, email: e.target.value });
setErrors({ ...errors, email: '' });
} else {
setErrors({ ...errors, email: 'Please Provide a valid email' });
setUserInfo({ ...userInfo, email: '' });
}
};
// get password
const handlePasswordChange = e => {
setUserInfo({ ...userInfo, password: e.target.value })
};
// handle login
const handleLogin = async e => {
e.preventDefault();
// console.log(email);
await signInWithEmailAndPassword(userInfo.email, userInfo.password);
const email = userInfo.email;
const { data } = await axios.post('http://localhost:5000/token', { email });
// console.log(data);
localStorage.setItem('accessToken', data.token);
navigate(from, { replace: true });
};
// handle google sign in
const handleGoogleSignin = () => {
signInWithGoogle();
};
return (
<div className="mt-5">
<div className="w-50 mx-auto mt-5 login-form p-5">
<h3 className="text-center mb-3 login-title">Log in</h3>
<Form onSubmit={handleLogin}>
<Form.Group className="mb-3" controlId="formBasicEmail">
<Form.Label>Email address</Form.Label>
<Form.Control onChange={handleEmailChange} type="email" placeholder="Enter email" />
{errors?.email && <p className='text-danger'>{errors.email}</p>}
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicPassword">
<Form.Label>Password</Form.Label>
<Form.Control onChange={handlePasswordChange} type="password" placeholder="Password" />
</Form.Group>
<Button variant="danger" type="submit" className="w-100">
Login
</Button>
</Form>
<Button onClick={handleGoogleSignin} variant="" type="submit" className="w-100 my-2 google-btn mt-4">
<FcGoogle className='g-icon'></FcGoogle> Sign in with Google
</Button>
<button onClick={handleResetPass} className="btn btn-link">Forgot password?</button>
<p>Don't have an account? <button onClick={() => navigate('/signup')} className="btn btn-link">Create an account</button></p>
</div>
</div>
);
};
export default Login;
You have to handle the error state of the signInWithEmailAndPassword in a try/catch block.
In handleLogin():
try {
await signInWithEmailAndPassword(userInfo.email, userInfo.password);
const email = userInfo.email;
const { data } = await axios.post("http://localhost:5000/token", { email });
localStorage.setItem("accessToken", data.token);
navigate(from, { replace: true });
} catch (error) {
//handle error state
}
Got my Landing page in here with hardcoded username / password into firebase db.
after successful login, I am redirected to the homepage. However, I am trying to figure out how to fetch the data for the specific logged in user. Currently, in my Firebase I have only 1 Collection which is Users and contains some documents any of the documents has their own fields it is all hardcoded for the sake of the test.
After the log in I am currently logging data but I only see the last added document. How do i attach the User to see its own data. I tried creating directly in firebase a document with the same UID as the logging user but the data that i am logging is still the last added document instead of the right for the specific user.
function LandingPage(props) {
const [showErrorModal, setShow] = useState(false);
const emailInputRef = useRef();
const passwordInputRef = useRef();
const navigate = useNavigate();
function sumbitForm(e) {
e.preventDefault();
const enteredEmail = emailInputRef.current.value;
const enteredPassword = passwordInputRef.current.value;
const url = 'https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=AIzaSyCNBAxjeKNoAPPjBV0JW4vZ0QaTaOx9-L4';
fetch(url, {
method: 'POST',
body: JSON.stringify({
email: enteredEmail,
password: enteredPassword,
returnSecureToken: true,
}),
headers: {
'Content-Type': 'application/json',
},
}).then((res) => {
if (res.ok) {
navigate('/homepage')
} else {
setShow(true);
}
return res.json()
}).then((data) =>
console.log(data))
}
function handleClose() {
setShow(false)
}
return (
<div className='wrapper'>
<form onSubmit={sumbitForm}>
<h3>Login Here</h3>
<label htmlFor="username">Username</label>
<input type="text" placeholder="Sigh up with email" id="username" ref={emailInputRef} ></input>
<label htmlFor="password">Password</label>
<input type="password" placeholder="Password" id="password" ref={passwordInputRef}></input>
<button className='button' type="submit" typeof='submit' >Log In</button>
{showErrorModal ? <Modal show={showErrorModal} onHide={handleClose}
backdrop="static">
<Modal.Header>
<Modal.Title>Incorrect Username/Password</Modal.Title>
</Modal.Header>
<Modal.Body>
Please provide the correct credentials
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
</Modal.Footer>
</Modal> : null}
<div className='landingpage-logo'>
<img src={logo} className="landingpage-logo"></img>
</div>
</form>
</div>
)
}
export default LandingPage;
import React, { useEffect, useState } from "react";
import { getDatabase, ref, onValue } from "firebase/database";
import { db, firebase } from '../../firebase';
import 'firebase/compat/auth';
const HomeScreen = (props) => {
const [loadedData, setLoadedData] = useState([]);
const username = props.email.substring(0, props.email.indexOf('#'))
useEffect(() => {
readData();
}, [])
async function readData() {
db.collection('Users').get().then((querySnapshot) => {
querySnapshot.forEach(element => {
const incomingData = element.data();
setLoadedData(incomingData)
})
})
}
return (
<div className={styles['wrapper']}>
</div>
)
}
export default HomeScreen;
I created a simple project in react by using firebase to use crud proccessing.
https://github.com/celalaygar/web-push/tree/master/react-firebase-CRUD-example
in package.json->dependencies : "firebase": "^7.14.1"
in this file fetch data method is here.
https://github.com/celalaygar/web-push/blob/master/react-firebase-CRUD-example/src/components/main.component.js
fetchData = async () => {
const db = firebase.firestore();
const data = await db.collection("spell").get();
result = data.docs.map(doc => ({ ...doc.data(), id: doc.id }));
this.setState({ spell: result });
}
Endpoint
const mongoose = require("mongoose");
const CreateBio = mongoose.model("bios");
// exports.baseRoute = async (req, res) => {
// res.send("Server Running");
// };
exports.createBio = async (req, res) => {
console.log(req.body);
let userBio = new CreateBio({
userBio: req.body.userBio
});
console.log('userBio:', userBio);
await userBio.save((err, data) => {
if (err) {
// if there is an error send the following response
res.status(500).json({
message: "Something went wrong, please try again later.",
});
} else {
// if success send the following response
res.status(200).json({
message: "Bio Created",
data,
});
}
});
};
exports.displayBio = async (req, res) => {
// get id from URL by using req.params
let userBioID = req.params.id;
console.log(userBioID);
// we use mongodb's findById() functionality here
await CreateBio.findById({ _id: userBioID }, (err, data) => {
if (err) {
console.log(err)
res.status(500).json({
message: "Something went wrong, please try again later.",
});
} else {
console.log(data);
res.status(200).json({
message: "bio found",
data,
});
}
});
};
Frontend
import React, { useState, useEffect } from "react";
import { useHistory } from "react-router-dom";
import { isExpired, decodeToken } from "react-jwt";
import Form from "react-bootstrap/Form";
import Button from "react-bootstrap/Button";
import Container from "react-bootstrap/Container";
import Card from "react-bootstrap/Card";
import "./tests/home-test.css";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import Navi from "../Navigation/nav";
import Image from "react-bootstrap/Image";
import axios from "axios";
import Nav from "react-bootstrap/Nav";
//import { displayBio } from './displayBio';
// import "./login.css";
const Home = () => {
//const [someProperty, setSomeProperty] = useState([]);
const [userBio, setBio] = useState("")
const history = useHistory();
const loadBio = async () => {
try{
let res = await axios.get('http://localhost:5000/displaybio/:id')
setBio(res.data.data.userBio)
console.log(res.data.data.userBio)
} catch (err){
console.log(err)
}
}
useEffect(() => {
// console.log("use effect working!");
if (!window.localStorage.getItem("token")) {
//redirect to login
console.log("redirect to login");
history.push("/");
}
if (window.localStorage.getItem("token")) {
const isMyTokenExpired = isExpired(window.localStorage.getItem("token"));
console.log(isMyTokenExpired);
if (isMyTokenExpired) {
console.log("redirect to login");
history.push("/");
}
const myDecodedToken = decodeToken(window.localStorage.getItem("token"));
console.log(myDecodedToken);
}
// fetch('http://localhost:5000/displayBio/:id', {
// method: "GET"
// })
// .then(res => res.json())
// .then(response => { setBio(response.item)
// })
loadBio()
}, []);
return (
<div className="Home">
<Container className="homeContainer shadow mt-2">
<Row>
<Col className="d-flex align-items-center">
<span>Home (You are logged in)</span>
</Col>
<Col className="">
<div className="d-flex align-items-center justify-content-end">
<Button
className="logoutBtn mb-2 mt-2"
onClick={(e) => {
window.localStorage.removeItem("token");
this.props.history.push("/");
}}
>
Logout
</Button>
</div>
</Col>
</Row>
<Form>
<Card className="profileCard">
<Card.Body>
<Card.Title className="text-center">
<div>
<Navi />
</div>
<h1>
Welcome Back <span className="text-success">Username</span>
</h1>
</Card.Title>
<Container>
<Row>
<Col className="d-flex justify-content-center col-12">
<div className="profilepic text-center">
Add a Profile Picture here!
</div>
</Col>
<Col className="mt-n5">
<div className="col-12 text-center">
<Card.Text
className="cardText text-center col-lg-10"
value={userBio}
//onChange={setBio}
></Card.Text>
<div className="mt-3">
<Button
className="shareVsBtn"
variant="success"
type="submit"
href="/sharewall"
>
Shared Verse
</Button>
</div>
<div className="mt-3">
<Button
className="postSubBtn mb-3"
variant="success"
type="submit"
href="/postverse"
>
Post a Verse
</Button>
</div>
</div>
</Col>
</Row>
</Container>
</Card.Body>
</Card>
</Form>
</Container>
</div>
);
}
export default Home;
Every time I try to send the request I end up getting a 500 error.500
I cannot seem to get it to console.log any of the information on the front end. I am not sure if I am not just formatting my hook right or not. I am able to get my response on the backend using postman. But my get request from the front end is not going through. Stating that I am having failure at casting {_id :id} at path _id for my model bios.
In order for you to see your userBio you need to have the handlebars inside the Card.Text selector (I omitted the className for this example). This will allow you to see the data in the front end. This is a result by taking the id from mongo and pasting it in the http address i.e: http://localhost:5000/displaybio/123456789.
<Card.Text value={userBio.id}>{userBio}</Card.Text>
In your loadBio you need to console.log(res); to find where the code is in the data object. In this case: setBio(res.data.data.userBio). This the answer to see the data displayed, Cody still needs an answer on how to grab the data dynamically by the id. displaybio/${id} doesn't work.