Firebase Error: User does not have access - reactjs

I am working on a snapchat clone where I want to use the image which is cliked on webcam to store in firestore and use it as preview. The code is perfect but it's showing an error related to firebase. I have no idea what to do.
This is my code
import "./Preview.css"
import { resetCameraImage, selectCameraImage } from './../features/cameraSlice';
import { useSelector, useDispatch } from 'react-redux';
import { useHistory } from 'react-router';
import CloseIcon from "#material-ui/icons/Close";
import TextFieldsIcon from "#material-ui/icons/TextFields";
import CreateIcon from "#material-ui/icons/Create";
import NoteIcon from "#material-ui/icons/Note";
import MusicNoteIcon from "#material-ui/icons/MusicNote";
import AttachFileIcon from "#material-ui/icons/AttachFile";
import CropIcon from "#material-ui/icons/Crop";
import TimerIcon from "#material-ui/icons/Timer";
import SendIcon from "#material-ui/icons/Send";
import { v4 as uuid } from "uuid";
import { db, storage } from "./firebase";
import firebase from 'firebase';
function Preview() {
const cameraImage = useSelector(selectCameraImage);
const history = useHistory();
const dispatch = useDispatch();
useEffect(() => {
if (!cameraImage) {
history.replace('/');
}
}, [cameraImage, history]);
const closePreview = () => {
dispatch(resetCameraImage());
}
const sendPost = () => {
const id = uuid();
const uploadTask = storage.ref(`posts/${id}`).putString(cameraImage, "data_url");
uploadTask.on('state_changed', null, (error) => {
// error function
console.log(error);
},
() => {
// complete function
storage.ref('posts').child(id).getDownloadURL().then((url) => {
db.collection('posts').add({
imageUrl: url,
username: "PAPA React",
read: false,
//profilePic,
timestamp: firebase.firestore.FieldValue.serverTimestamp(),
});
history.replace('/chats');
});
}
);
};
return (
<div className="preview">
<CloseIcon className="preview__close" onClick={closePreview}/>
<div className="preview__toolbarRight">
<TextFieldsIcon />
<CreateIcon />
<NoteIcon />
<MusicNoteIcon />
<AttachFileIcon />
<CropIcon />
<TimerIcon />
</div>
<img src={cameraImage} alt="" />
<div className="preview__footer" onClick={sendPost} >
<h2>Send Now</h2>
<SendIcon fontSize="small" className="preview__sendIcon" />
</div>
</div>
)
}
export default Preview
Error thrown
My firebase rule settings
Same error on an alternate method
Same error on an alternate method

The error said the users does not have access to your Firebase Storage. Add rules for Firebase Storage to give users access. For example:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write;
}
}
}

Related

React useContext is returning undefined

I am trying to use context with my Gatsby project. I have successfully implemented this in my previous project and I have copied the code over to my new project and it's not working as intended.
This is my context.js file:
import React, { useContext, useState } from "react";
const defaultState = {
isLoggedIn: false,
};
const AuthContext = React.createContext();
export function useAuth() {
return useContext(AuthContext);
}
export function AuthProvider({ children }) {
const [isLoggedIn, setIsLoggedIn] = useState(false);
function toggle() {
console.log("BOO!");
}
const value = {
isLoggedIn,
setIsLoggedIn,
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
This is my app.js file:
import React from "react";
import { Router } from "#reach/router";
import IndexPage from "./index";
import ProjectPage from "./project";
import { AuthProvider } from "../contexts/context";
const App = () => (
<AuthProvider>
<Router basepath="/app">
<IndexPage path="/" component={IndexPage} />
<ProjectPage path="/project" component={ProjectPage} />
</Router>
</AuthProvider>
);
export default App;
This is my index.js file:
import React, { useContext } from "react";
import { Link } from "gatsby";
import { useAuth } from "../contexts/context";
import { AuthContext } from "../contexts/context";
const IndexPage = () => {
console.log(useAuth())
return (
<div className="w-40 h-40 bg-red-400">
{/*<Link to="/project">to projects</Link>*/}
<div>Click me to toggle: uh</div>
</div>
);
};
export default IndexPage;
useAuth() should return the desired components and functions but instead is always returning undefined. I have looked over my previous code as well as snippets on stack overflow and I can't seem to find the correct fix.
The following includes code that successfully built and executed:
Original context.js
import '#stripe/stripe-js'
/* Functionality */
import React, { useContext, useEffect, useState } from "react";
import { navigate } from "#reach/router";
import firebase from 'gatsby-plugin-firebase';
import { useLocalStorage } from 'react-use';
const AuthContext = React.createContext()
export function useAuth() {
return useContext(AuthContext)
}
export function AuthProvider({ children }) {
const [isLoggedIn, setIsLoggedIn] = useState(false)
const [isLoading, setIsLoading] = useLocalStorage("loading", false);
// Sign In
const signInWithRedirect = (source) => {
let provider;
switch(source) {
case 'Google':
provider = new firebase.auth.GoogleAuthProvider()
break;
case 'Github':
provider = new firebase.auth.GithubAuthProvider()
break;
default:
break;
}
setIsLoading(true)
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.SESSION)
.then(() => {
// Existing and future Auth states are now persisted in the current
// session only. Closing the window would clear any existing state even
// If a user forgets to sign out.
// ...
// New sign-in will be persisted with session persistence.
return firebase.auth().signInWithRedirect(provider)
})
.catch((error) => {
// Handle Errors here.
let errorCode = error.code;
let errorMessage = error.message;
});
}
// Sign Out
const signOut = () => {
firebase.auth().signOut().then(() => {
// Sign-out successful.
setIsLoggedIn(false)
navigate('/app/login')
}).catch((error) => {
// An error happened.
});
}
useEffect(() => {
firebase.auth().onAuthStateChanged((user) => {
try {
// If user is authenticated
if (!!user) {
// Fetch firestore document reference
var docRef = firebase.firestore().collection("study_guide_customers").doc(user.uid)
docRef.get().then((doc) => {
console.log('checking doc')
// If the document doesn't exist, create it and add to the firestore database
if (!doc.exists) {
console.log('inside customer')
const customer = {
customerCreationTimestamp: firebase.firestore.Timestamp.now(),
username: user.displayName,
email: user.email
}
firebase.firestore().collection("study_guide_customers").doc(user.uid).set(customer)
.then(() => {
// After docuement for user is created, set login status
setIsLoggedIn(!!user)
setIsLoading(false)
})
.catch((error) => {
console.error("Error writing document: ", error);
});
// If document for user exists, set login status
} else {
setIsLoggedIn(!!user)
setIsLoading(false)
}
})
}
} catch {
console.log('Error checking firestore existence and logging in...')
}
})
}, [isLoggedIn, isLoading, setIsLoading, setIsLoggedIn])
const value = {
signOut,
isLoggedIn,
isLoading,
setIsLoading,
setIsLoggedIn,
signInWithRedirect,
}
return (
<AuthContext.Provider value={value}>
{children}
</AuthContext.Provider>
)
}
Original app.js
/* Stripe Security */
import '#stripe/stripe-js'
/* Functionality */
import React from "react"
import { Router } from "#reach/router"
import PrivateRoute from "../components/PrivateRoute"
import Profile from "../components/Profile"
import Login from "../components/Login"
import Projects from "../components/Projects"
import IndexPage from "./index"
import NotFoundPage from './404'
import { AuthProvider } from "../contexts/context"
const App = () => (
<AuthProvider>
<Router basepath="/app">
<PrivateRoute path="/profile" component={Profile} />
<Login path="/login" component={Login}/>
<IndexPage path="/" component={IndexPage}/>
<Projects path="/projects" component={Projects} />
</Router>
</AuthProvider>
)
export default App
Original index.js
/* Stripe Security */
import '#stripe/stripe-js'
/* Functionality */
import * as React from "react"
import IndexContact from "../components/Index/Contact"
import IndexSelectedProjects from "../components/Index/SelectedProjects"
import IndexFeaturedProjects from "../components/Index/FeaturedProjects"
import IndexFooter from "../components/Index/Footer"
import IndexStudyGuide from "../components/Index/StudyGuide"
import IndexNavbar from "../components/Index/Navbar"
import IndexHeader from "../components/Index/Header"
import IndexAbout from '../components/Index/About'
import IndexExperience from '../components/Index/Experience'
import { useMount } from 'react-use';
const IndexPage = () => {
useMount(() => localStorage.setItem('loading', false));
return (
<>
<IndexNavbar />
<IndexHeader />
<IndexAbout />
<IndexExperience />
<IndexFeaturedProjects />
<IndexSelectedProjects />
<IndexStudyGuide />
<IndexContact />
<IndexFooter />
</>
)
}
export default IndexPage
Then in any component I could simply use the following code to access the context
import { useAuth } from "../contexts/context"
const { isLoggedIn, signInWithRedirect, isLoading } = useAuth()
Child components are mounted before parent. Fix your context.js file to add a default value for isLoggedIn state:
const defaultState = {
isLoggedIn: false,
setIsLoggedIn: () => {}
};
const AuthContext = React.createContext(defaultState);
Your defaultState should also include default methods for any parts of the context you wish to work with.

FirebaseError: Expected type 'vc', but it was: a custom rn object

I'm trying to get data from Firestore by using react-firebase-hooks: v5.0.3 but I keep getting the aforementioned error. I've also tried using onSnapshot but surely, the same error pops up. I've also tried importing collection and getFirestore from "firebase/firestore/" instead of "firebase/firestore/lite", but that pops up another error expected first argument to collection() to be a collectionreference, a documentreference or firebasefirestore.
Any help or suggestion will be appreciated.
import React from "react";
import classes from "./css/Sidebar.module.css";
import {
ChatAltIcon,
CubeTransparentIcon,
DotsVerticalIcon,
SearchIcon,
UserCircleIcon,
XIcon,
} from "#heroicons/react/solid";
import * as EmailValidator from "email-validator";
import { signOut } from "firebase/auth";
import { auth, db } from "../firebase";
import { collection, addDoc } from "firebase/firestore/lite";
import { useAuthState } from "react-firebase-hooks/auth";
import { useCollection } from "react-firebase-hooks/firestore";
import { onSnapshot, query, where } from "firebase/firestore";
function Sidebar() {
const [user] = useAuthState(auth);
const q = query(collection(db,"chats"),where("users", "array-contains", user.email));
// const [chatsSnapshot, loading, error] = useCollection(q); //same issue,
// console.log("ChatSnapshot error: ", error); //console logging "error" logs "undefined".
let data;
const unsubscribe = onSnapshot(q,(querySnapshot)=>{
data = querySnapshot.data;
});
console.log(data);
unsubscribe();
const createChat = () => {
const input = prompt(
"Please enter email address of the user you wish to chat with."
);
if (!input) return null;
if (
EmailValidator.validate(input) &&
input !== user.email &&
!chatAllReadyExists(input)
) {
//add chat to db if it already doesnt exist and also validate
addDoc(collection(db, "chats"), { users: [user.email, input] }).then(
(res) => console.log("doc added ", res)
);
}
};
const chatAllReadyExists = (recipentEmail) =>
!!chatsSnapshot?.docs.find(
(chat) =>
chat.data().users.find((user) => user === recipentEmail)?.length > 0
);
const userSignOut = () => {
signOut(auth).then((res) => {
console.log("You have been logged out!");
});
};
return (
<div className={classes.sidebarBlock}>
<div className={classes.header}>
<UserCircleIcon className={classes.user} onClick={userSignOut} />
<span className={classes.flexContainer}>
<CubeTransparentIcon className={classes["button"]} />
<ChatAltIcon onClick={createChat} className={classes["button"]} />
<DotsVerticalIcon className={classes["button"]} />
</span>
</div>
<div className={classes.searchBoxContainer}>
<SearchIcon className={classes.button} />
<input
className={classes.searchBar}
type="search"
placeholder="Search or start new chat"
/>
<XIcon className={classes.button} />
</div>
<div className={classes.contactList}>
<ul className={classes.listContainer}>
<li className={classes.listItem}>
<UserCircleIcon className={classes.user} />
<div className={classes.descContainer}>
<h3>Person's Name</h3>
<p>Last chat to read</p>
</div>
</li>
</ul>
</div>
</div>
);
}
export default Sidebar;
Firebase.js
import { getApps, initializeApp } from "firebase/app";
import { getAuth, GoogleAuthProvider } from "firebase/auth";
import { getFirestore } from "firebase/firestore/lite";
const firebaseConfig = {
apiKey: "***",
authDomain: "***.firebaseapp.com",
projectId: "***",
storageBucket: "***.appspot.com",
messagingSenderId: "***",
appId: "***",
};
let app;
if (getApps().length < 1) {
app = initializeApp(firebaseConfig);
}
const db = getFirestore(app);
const auth = getAuth();
const provider = new GoogleAuthProvider();
export { db, auth, provider };

How do I store firebase Auth data in firestore?

So I have a basic app running. There's just one button which is used to login with google and I want to store that user's info in firestore and then I want to map through every user and display every single user's which are signed in, in my app. Firebase auth is complete but I don't know how to store that user's auth info.Also I am using useContext to pass authorized users info.Here's the code:
Main Entry Level App.js
import React, { useEffect, useMemo, useState } from "react";
import Login from "./components/Login";
import { User } from "./components/User";
import db, { auth } from "./firebase";
import { UserContext } from "./Contexts/UserContext";
const App = () => {
const [user, setUser] = useState([]);
const value = useMemo(() => ({ user, setUser }), [user, setUser]);
useEffect(() => {
auth.onAuthStateChanged((user) => {
// console.log(user);
setUser(user);
});
}, []);
return (
<UserContext.Provider value={value}>
{user ? <User /> : <Login />}
</UserContext.Provider>
);
};
export default App;
User.js Component
import React, { useContext } from "react";
import { UserContext } from "../Contexts/UserContext";
import db, { auth } from "../firebase";
export const User = () => {
const { user } = useContext(UserContext);
return (
<>
<img src={user.photoURL} alt={user.displayName} />
<div>{user.displayName}</div>
<div>{user.email}</div>
<button onClick={() => auth.signOut()}>Log Out</button>
</>
);
};
Login.js
import React, { useContext, useEffect } from "react";
import { UserContext } from "../Contexts/UserContext";
import { auth, signInWithGoogle } from "../firebase";
const Login = () => {
const { setUser } = useContext(UserContext);
useEffect(() => {
auth.onAuthStateChanged((user) => {
console.log(user);
setUser(user);
});
});
return (
<>
<div style={{ textAlign: "center" }}>
<button onClick={signInWithGoogle}>
<img
src="https://img.icons8.com/ios-filled/20/000000/google-logo.png"
alt="google icon"
/>
<span> Continue with Google</span>
</button>
</div>
</>
);
};
export default Login;
signInWithGoogle
export const signInWithGoogle = () => {
auth.signInWithPopup(provider).catch((err) => alert(err.message));
};
You should use a then() block in your signInWithGoogle() function, as follows:
export const signInWithGoogle = () => {
auth.signInWithPopup(provider)
.then((result) => {
const userId = result.user.uid;
// Create a doc in a users collection
// It's up to you to build theJavaScript objec to pass to the set() methood
firestore.collection("users").doc(userId).set( {foo: bar, bar: foo} );
})
.catch((err) => alert(err.message));
};
More details in the doc.

Next JS code inside getInitialProps not executes after page reload

I'm integrating NextJS into my React app. I face a problem, on page reload or opening direct link(ex. somehostname.com/clients) my getInitialProps not executes, but if I open this page using <Link> from next/link it works well. I don't really understand why it happens and how to fix it. I have already came throught similar questions, but didn't find any solution which could be suitable for me.
Clients page code:
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { ClientsTable } from '../../src/components/ui/tables/client-table';
import AddIcon from '#material-ui/icons/Add';
import Fab from '#material-ui/core/Fab';
import { AddClientModal } from '../../src/components/ui/modals/add-client-modal';
import CircularProgress from '#material-ui/core/CircularProgress';
import { Alert } from '../../src/components/ui/alert';
import { Color } from '#material-ui/lab/Alert';
import { AppState } from '../../src/store/types';
import { thunkAddClient, thunkGetClients } from '../../src/store/thunks/clients';
import { SnackbarOrigin } from '#material-ui/core';
import { IClientsState } from '../../src/store/reducers/clients';
import { NextPage } from 'next';
import { ReduxNextPageContext } from '../index';
import { PageLayout } from '../../src/components/ui/page-layout';
const Clients: NextPage = () => {
const [addClientModalOpened, setAddClientModalOpened] = useState<boolean>(false);
const [alertType, setAlertType] = useState<Color>('error');
const [showAlert, setAlertShow] = useState<boolean>(false);
const alertOrigin: SnackbarOrigin = { vertical: 'top', horizontal: 'center' };
const dispatch = useDispatch();
const { clients, isLoading, hasError, message, success } = useSelector<AppState, IClientsState>(state => state.clients);
useEffect(() => {
if (success) {
handleAddModalClose();
}
}, [success]);
useEffect(() => {
checkAlert();
}, [hasError, success, isLoading]);
function handleAddModalClose(): void {
setAddClientModalOpened(false);
}
function handleAddClient(newClientName: string): void {
dispatch(thunkAddClient(newClientName));
}
function checkAlert() {
if (!isLoading && hasError) {
setAlertType('error');
setAlertShow(true);
} else if (!isLoading && success) {
setAlertType('success');
setAlertShow(true);
} else {
setAlertShow(false);
}
}
return (
<PageLayout>
<div className='clients'>
<h1>Clients</h1>
<div className='clients__add'>
<div className='clients__add-text'>
Add client
</div>
<Fab color='primary' aria-label='add' size='medium' onClick={() => setAddClientModalOpened(true)}>
<AddIcon/>
</Fab>
<AddClientModal
opened={addClientModalOpened}
handleClose={handleAddModalClose}
handleAddClient={handleAddClient}
error={message}
/>
</div>
<Alert
open={showAlert}
message={message}
type={alertType}
origin={alertOrigin}
autoHideDuration={success ? 2500 : null}
/>
{isLoading && <CircularProgress/>}
{!isLoading && <ClientsTable clients={clients}/>}
</div>
</PageLayout>
);
};
Clients.getInitialProps = async ({ store }: ReduxNextPageContext) => {
await store.dispatch(thunkGetClients());
return {};
};
export default Clients;
thunkGetClients()
export function thunkGetClients(): AppThunk {
return async function(dispatch) {
const reqPayload: IFetchParams = {
method: 'GET',
url: '/clients'
};
try {
dispatch(requestAction());
const { clients } = await fetchData(reqPayload);
console.log(clients);
dispatch(getClientsSuccessAction(clients));
} catch (error) {
dispatch(requestFailedAction(error.message));
}
};
}
_app.tsx code
import React from 'react';
import App, { AppContext, AppInitialProps } from 'next/app';
import withRedux from 'next-redux-wrapper';
import { Provider } from 'react-redux';
import { makeStore } from '../../src/store';
import { Store } from 'redux';
import '../../src/sass/app.scss';
import { ThunkDispatch } from 'redux-thunk';
export interface AppStore extends Store {
dispatch: ThunkDispatch<any, any, any>;
}
export interface MyAppProps extends AppInitialProps {
store: AppStore;
}
export default withRedux(makeStore)(
class MyApp extends App<MyAppProps> {
static async getInitialProps({
Component,
ctx
}: AppContext): Promise<AppInitialProps> {
const pageProps = Component.getInitialProps
? await Component.getInitialProps(ctx)
: {};
return { pageProps };
}
render() {
const { Component, pageProps, store } = this.props;
return (
<>
<Provider store={store}>
<Component {...pageProps} />
</Provider>
</>
);
}
}
);
Looking for your advices and help. Unfortunately, I couldn't find solution by myself.
This is the way Next.js works, it runs getInitialProps on first page load (reload or external link) in the server, and rest of pages that where navigated to with Link it will run this method on client.
The reason for this is to allow Next.js sites to have "native" SEO version.

React.js page does not switch

I'm trying to control the page using react-hook, react-router-dom, redux.
The login screen is implemented and the code that tries to switch to the main page when the login is successful is written.
So I used history.push of react-router.
However, history.push only changes the browser url, not the actual information displayed on the page.
The code is shown below.
In brief code explanation,
The id and password are put into redux and get as getelementbyuId and sent as form data.
The login function works normally.
history.push ('/') written to "userUpdateUserInfo" doesn't work at all.
Only the url of the browser changes, not the main page.
App.tsx
import React from 'react';
import { Route, Switch } from 'react-router-dom';
import { Main, Login } from './pages';
import './css/App.css';
const App: React.FC = () => {
return (
<div>
<div className="App-contents-area">
<Switch>
<Route exact path="/" component={Login} />
<Route exact path="/main" component={Main} />
{/* <Redirect path="*" to="/" /> */}
</Switch>
</div>
</div>
);
}
export default App;
LoginPage.tsx
import React from 'react';
import { Login } from 'Component';
function LoginPage() {
return (
<Login />
);
}
export default LoginPage;
Login.tsx (components)
import React from 'react';
import {
LoginTitle, LoginAvatar, LoginUserId, LoginUserPassword, LoginButton
} from '..';
import '../../css/Login.css';
function Login() {
return (
<div className="Login">
<div className="Login-form-data">
<LoginTitle /> // code skip
<LoginAvatar /> // code skip
<LoginUserId /> // code skip
<LoginUserPassword /> // code skip
<LoginButton />
</div>
</div>
);
}
export default Login;
LoginButton.tsx (components)
import React from 'react';
import { useUpdateUserInfo } from 'Hook';
function LoginButton() {
const { handleLogin } = useUpdateUserInfo(); // custom hook
return (
<div className="LoginButton">
<button className="LoginButton-button" onClick={handleLogin}>Login</button>
</div>
);
}
export default LoginButton;
userUpdateUserInfo.tsx (custom hook)
import { useCallback } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { RootState } from 'Store/modules';
import { updateUserInfo } from 'Store/modules/user';
import { userLoginStatus } from 'Store/modules/login';
import { msg } from 'Lang';
import {
axiosPost, history,
_ShowFail, _ShowSuccess, _ShowSelect
} from 'Module';
export default function useUpdateUserInfo () {
const { id, name, tel, email } = useSelector((state: RootState) => state.user);
let { isLogin } = useSelector((state: RootState) => state.login);
const dispatch = useDispatch();
const handleLogin = useCallback(async () => {
try {
const userId: string = (document.getElementById('LoginUserId-id') as HTMLInputElement).value.trim();
const userPw: string = (document.getElementById('LoginUserPassword-password') as HTMLInputElement).value.trim();
if (!userId.length) { return _ShowFail(msg.pleaseInputUserId); }
if (!userPw.length) { return _ShowFail(msg.pleaseInputUserPassword); }
const formData: FormData = new FormData();
formData.append('userId', userId);
formData.append('userPw', userPw);
const url = '/login/check-login-info';
const config = {
headers: {
'Content-Type': 'multipart/form-data',
},
};
const res = await axiosPost(url, formData, config);
if (res.data.res) {
_ShowSuccess('login success');
const userInfo = {
id: res.data.rows[0].id,
name: res.data.rows[0].name,
email: res.data.rows[0].email,
tel: res.data.rows[0].tel,
};
isLogin = true;
/**************************/
history.push('/main'); // now working
/**************************/
dispatch(updateUserInfo(userInfo));
dispatch(userLoginStatus({ isLogin }));
}
else {
_ShowFail('login fail');
isLogin = false;
dispatch(updateUserInfo({ id, email, name, tel }));
dispatch(userLoginStatus({ isLogin }));
}
}
catch (error) {
_ShowFail(error.message);
}
}, [dispatch]);
return { handleLogin };
};
MainPage.tsx
import React from 'react';
function MainPage() {
return (
<div>
<h2>MainPage!!</h2>
</div>
);
}
export default MainPage;
history.tsx
import { createBrowserHistory } from 'history'
export default createBrowserHistory();
Since last night, I have been suffering from this problem.
How can I change the content of the page?
In App.js your Routes suppose to be inside < Router > < /Router >,
https://reacttraining.com/react-router/web/api/Router
(unless you wrap it on index.js that not including here and App is imported inside there)?

Resources