Я новичок в Firebase и React Native. Когда я добавляю в приложение аутентификацию по электронной почте и обновляю правила аутентификации, я получаю сообщение об ошибке Отсутствуют или недостаточно привилегий .
Я получаю сообщение об ошибке при попытке записи в Firestore в функции componentDidMount в Экран 1.
Я добавил следующие правила для своего приложения.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
Если я перейду на allow read, write: if true;
, все будет работать нормально. Однако это не то, что мне нужно для производственного приложения, которое я планирую развернуть.
Я проверил свое приложение, вытащив текущего пользователя, и похоже, что пользователь вошел в систему и прошел проверку подлинности.
И я получаю сообщение об ошибке аутентификации: [FirebaseError: Отсутствуют или недостаточны разрешения.], Когда я пытаюсь сделать следующее:
Config. js
import Firebase from "firebase";
// Web App Firebase Configuration
var firebaseConfig = {
apiKey: "pretendapikeytoprotect",
authDomain: "pretendapp.firebaseapp.com",
databaseURL: "https://pretendapp.firebaseio.com",
projectId: "pretendapp",
storageBucket: "pretendapp.appspot.com",
messagingSenderId: "messengerSenderIDnumbers",
appId: "appIDNumber",
measurementId: "measureIDnumberiD"
};
const app = Firebase.initializeApp(firebaseConfig);
// Initialize Cloud Firestore through firebase
export const db = app.firestore();
db.settings({experimentalForceLongPolling: true});
App. js
/**
* @format
* @flow strict-local
*/
import 'react-native-gesture-handler';
import React, {Component} from 'react';
import Providers from './src/navigation';
import {
Alert,
I18nManager,
YellowBox
} from 'react-native';
//Ignore Warning about Setting a Timer/No known fix at this time.
YellowBox.ignoreWarnings(['Setting a timer']);
type Props = {};
export default class App extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
}
componentWillUnmount() {
//willMountFunctions
}
componentDidMount() {
//DidMountFunctions
}
render() {
return (
<Providers />
)
}
}
Провайдеры - /src/navigation/index.js
import React from 'react';
import { AuthProvider } from './AuthProvider';
import Routes from './Routes';
export default function Providers() {
return (
<AuthProvider>
<Routes />
</AuthProvider>
);
}
Маршруты. js
import React, { useContext, useState, useEffect } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import auth from '@react-native-firebase/auth';
import AuthStack from './AuthStack';
import HomeStack from './HomeStack';
import { AuthContext } from './AuthProvider';
import Loading from '../components/Loading';
export default function Routes() {
const { user, setUser } = useContext(AuthContext);
const [loading, setLoading] = useState(true);
const [initializing, setInitializing] = useState(true);
// Handle user state changes
function onAuthStateChanged(user) {
setUser(user);
if (initializing) setInitializing(false);
setLoading(false);
if (user) {
console.log('user is logged');
}
}
useEffect(() => {
const subscriber = auth().onAuthStateChanged(onAuthStateChanged);
return subscriber; // unsubscribe on unmount
}, []);
if (loading) {
return <Loading />;
}
return (
<NavigationContainer>
{user ? <HomeStack /> : <AuthStack />}
</NavigationContainer>
);
}
HomeStack. js
import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
//Import Components
import HomeScreen from '../screens/HomeScreen';
import Screen1 from '../screens/Screen1';
const Stack = createStackNavigator();
export default function HomeStack() {
return (
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home"
component = {HomeScreen}
options={{ title: 'Home Screen' }} />
<Stack.Screen name="Screen1"
component={Screen1}
options={{ title: 'Screen 1' }} />
</Stack.Navigator>
);
}
Файл-помощник (helpers. js)
const RNFS = require('react-native-fs');
import storage from '@react-native-firebase/storage';
import firestore from '@react-native-firebase/firestore';
import { db } from '../config';
import { Platform } from 'react-native';
import { currentUser } from '../navigation/AuthProvider';
import auth from '@react-native-firebase/auth';
// removed other functions not relevant to question //
export const WriteSessionData = async (sessionID) => {
console.log("Write Session current User Logged in ", currentUser.uid);
console.log("Current Session User in Write Session ", auth().currentUser)
const session = db.collection('sessions').doc(sessionID);
await session.set({
name: '',
email: '',
timedate : Date.now(),})
.then(() => {
console.log("Session Data Added to Database");
}).catch((err) => {
console.log("Error in Writing to Database ", "User Logged in as: ", currentUser.uid, err);
});
}
}
AuthStack. js
import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import SignupScreen from '../screens/SignupScreen';
import LoginScreen from '../screens/LoginScreen';
const Stack = createStackNavigator();
export default function AuthStack() {
return (
<Stack.Navigator initialRouteName='Login'>
<Stack.Screen
name='Login'
component={LoginScreen}
options={{ header: () => null }}
/>
<Stack.Screen name='Signup' component={SignupScreen} />
</Stack.Navigator>
);
}
Экран входа
import React, { useState, useContext } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Image } from 'react-native';
import FormButton from '../components/FormButton';
import FormInput from '../components/FormInput';
import { AuthContext } from '../navigation/AuthProvider';
export default function LoginScreen({ navigation }) {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const { login } = useContext(AuthContext);
return (
<View style={styles.container}>
<FormInput
value={email}
placeholderText='Email'
onChangeText={userEmail => setEmail(userEmail)}
autoCapitalize='none'
keyboardType='email-address'
autoCorrect={false}
/>
<FormInput
value={password}
placeholderText='Password'
onChangeText={userPassword => setPassword(userPassword)}
secureTextEntry={true}
/>
<FormButton buttonTitle='Login' onPress={() => login(email, password)} />
<TouchableOpacity
style={styles.navButton}
onPress={() => navigation.navigate('Signup')}
>
<Text style={styles.navButtonText}>New user? Join here</Text>
</TouchableOpacity>
</View>
);
}
AuthProvider. js
import React, { createContext, useState } from 'react';
import auth from '@react-native-firebase/auth';
export const AuthContext = createContext({});
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
return (
<AuthContext.Provider
value={{
user,
setUser,
login: async (email, password) => {
try {
await auth().signInWithEmailAndPassword(email, password);
} catch (e) {
console.log(e);
}
},
register: async (email, password) => {
try {
await auth().createUserWithEmailAndPassword(email, password);
} catch (e) {
console.log(e);
}
},
logout: async () => {
try {
await auth().signOut();
} catch (e) {
console.error(e);
}
}
}}
>
{children}
</AuthContext.Provider>
);
};
export const currentUser = auth().currentUser;
HomeScreen. js
import React, { Component, useContext, useState} from 'react';
import { Alert, Button, View, Text, Image, PermissionsAndroid, TouchableHighlight, TextInput } from 'react-native';
import { styles, buttons } from './styles'
import auth from '@react-native-firebase/auth';
import FormButton from '../components/FormButton';
import { AuthContext } from '../navigation/AuthProvider';
export default function HomeScreen(props) {
const { route, navigation } = props
const { user, logout } = useContext(AuthContext);
function navigate() {
console.log("User Logged In", auth().currentUser.uid);
console.log("Navigating to Screen 1 ....");
navigation.navigate('Screen1');
}
return (
<View>
<View style={styles.container}>
<Text style={styles.description}>You are logged in as {user.email}</Text>
<FormButton buttonTitle="Get Started" onPress={()=> navigate()} />
<FormButton buttonTitle='Logout' onPress={() => logout()} />
</View>
</View>
);
}
Screen1. js
import React, { Component } from 'react';
import { Alert, Button, View, Text, Image, PermissionsAndroid, TouchableHighlight } from 'react-native';
import { styles } from './styles'
import { db } from '../config';
import { WriteSessionData} from '../utils/helpers';
import storage from '@react-native-firebase/storage';
import { currentUser } from '../navigation/AuthProvider';
import FormButton from '../components/FormButton';
class Screen1 extends Component {
_isMounted = false;
constructor(props) {
super(props);
this.state = {
sessionID: '12345' //random id that will be passed down
};
}
componentWillUnmount() {
clearInterval(this._progressInterval);
this._isMounted = false;
}
componentDidMount() {
this._isMounted = true;
console.log("User ID in Screen 1 componentDidMount", currentUser.uid);
WriteSessionData(this.state.sessionID);
if(this._isMounted){
//do some other commands
}
}
render() {
return (
<View>
<Text style={styles.title}>Screen 1</Text>
<Text style={styles.description}>User Email: {currentUser.email}
</Text>
</View>
);
}
}
export default Screen1;
Я даже могу вернуть пользователя UID в console.log. Я также вижу, что пользователь вошел в систему через веб-консоль Firebase.
Мне не хватает добавления некоторых привилегий в IAM? Есть ли проблема с заголовком ответа с библиотеками React Native или что-то, что я должен решить.
У меня установлены следующие библиотеки и версии:
"@react-native-firebase/app": "^8.2.0",
"@react-native-firebase/auth": "^8.2.0",
"@react-native-firebase/firestore": "^7.4.3",
"@react-native-firebase/storage": "^7.2.2",
"@react-navigation/native": "^5.6.1",
"@react-navigation/stack": "^5.6.2",
"firebase": "^7.16.0",
"react": "16.11.0",
"react-native": "0.62.2",