Пользователь Firebase аутентифицирован, так почему загрузка в хранилище запрещена? - PullRequest
0 голосов
/ 22 января 2020

В реактивном проекте я использую и react-native-firebase и firebase sdk. react-native-firebase не разрешает использовать хранилище Firebase для загрузки блобов изображений, поэтому я использую ванильный Firebase javascript SDK для выполнения этой части. Ради различий, в моем коде и этом посте я идентифицирую firebase javascript sdk как 'FIREBASE', а react-native-firebase как 'firebase'.

Мне пришлось инициализировать мое приложение firebase (хотя react-native-firebase не требует этого для своей функции, firebase делает), приложение. js конструктор и импорт:

 import * as React from 'react';
 import AppNavigation from './src/navigation';
 import { Provider } from 'react-redux';
 import { store, persistor } from './src/store/index.js';
 import firebase from 'firebase/app';
 import { PersistGate } from 'redux-persist/integration/react';
 export default class App extends React.Component {
   constructor (props) {
     super(props);
     const firebaseConfig = {
        apiKey: '{apiKey}',
        authDomain: 'project-ID.firebaseapp.com',
        databaseURL: 'https://project-ID.firebaseio.com',
        projectId: 'project-ID',
        storageBucket: 'project-ID.appspot.com',
        messagingSenderId: '9999999999'
     };
     if (!firebase.apps.length) {
        firebase.initializeApp(firebaseConfig);
     }
  }

Я реализую firebase и FIREBASE в действии (firebase для auth / firestore и FIREBASE для хранилища):

import * as types from '../actions/types';
import RNFetchBlob from 'rn-fetch-blob';
import firebase from 'react-native-firebase';
import * as FIREBASE from 'firebase/app';
import 'firebase/storage';
import { Platform } from 'react-native';
const Blob = RNFetchBlob.polyfill.Blob;
const fs = RNFetchBlob.fs;

export const registerUser = (registration) => {
    const { email, pass, username, img } = registration;
    return (dispatch) => {
        dispatch({ type: types.REGISTER_USER });
        console.log('starting registration process...');
        // check username is unique
        firebase
            .firestore()
            .collection('users')
            .where('username', '==', username)
            .get()
            .then((querySnapshot) => {
                if (querySnapshot.empty !== true) {
                    // back to registration form
                    registrationFail(dispatch, 'Username already taken. Try again.');
                    console.log("Registrant's username already exists");
                } else {
                    console.log('Registrants username is unique');
                    // continue with registration
                    firebase
                        .auth()
                        .createUserWithEmailAndPassword(email, pass)
                        .then((userCredential) => {
                            // successful user creation, now authenticated
                            // write to img storage
                            uploadImg(dispatch, img, userCredential.user.uid)
                                .then((imgUrl) => {
                                    // on success, write to firestore
                                    uploadImgSuccess(dispatch, 'Profile image upload successful...');
                                    // write rest of data to firestore
                                        firebase
                                            .firestore()
                                            .collection('users')
                                            .add({
                                                createdAt: firebase.firestore.FieldValue.serverTimestamp(),
                                                username: email,
                                                uid: userCredential.user.uid,
                                                profileImg: imgUrl,
                                                email: email,
                                            })
                                            .catch((err) => {
                                                console.log('Registration failed. Error: ' + err.message);
                                                registrationFail(dispatch, err.message);
                                            });
                                    }
                                })
                                .catch((err) => {
                                    // Image Profile NOT Uploaded
                                    uploadImgFail(dispatch, err);
                                });
                        })
                        .catch((err) => {
                            // unsuccessful user creeation
                            registrationFail(dispatch, err.message);
                        });
                }
            })
            .catch((err) => registrationFail(dispatch, err.message));
    };
};
const uploadImg = async (dispatch, uri, uid, mime = 'image/png') => {
    console.log('Starting image upload...');
    dispatch({ type: types.UPLOAD_IMG, info: 'Uploading profile image...' });
    const uploadUri = Platform.OS === 'ios' ? uri.replace('file://', '') : uri;
    let uploadBlob = null;
    // let downloadPath = '';
    const imageRef = FIREBASE.storage().ref(uid).child('profileImg');
    fs
        .readFile(uploadUri, 'base64')
        .then((data) => {
            return Blob.build(data, { type: `${mime};BASE64` });
        })
        .then((blob) => {
            uploadBlob = blob;
            return imageRef.put(blob, { contentType: mime });
        })
        .then(() => {
            uploadBlob.close();
            return imageRef.getDownloadURL();
        })
        .then((url) => {
            console.log('Returning Download URL: ' + url);
            uploadImgSuccess(dispatch, 'Image upload successful...');
        })
        .catch((err) => {
            uploadImgFail(dispatch, 'Image  upload failed: ' + JSON.stringify(err));
        });
};

, но когда я go через uploadImg(), я получаю ошибку:

{ 
  "code_": "storage/unauthorized", 
  "message":"Firebase Storage: User does not have permission to access 'someReference/someChild', 
  "serverResponse":{"Code":403, "message": "permission denied."}
}

Вот Firestore правило:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
} 

Вот правило хранения:

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}

Я не понимаю, что происходит и почему. Пользователь аутентифицируется во время реакции-native-firebase createUserWithEmailAndPassword() и даже может загружать данные в Firestore. Мое единственное предположение, что это, возможно, связано с использованием как firebase & FIREBASE, так и с тем, как я настроил firebase с FIREBASE. Я использовал оба вместе в предыдущем тестовом проекте, и он успешно работал с помощью разветвленного проекта rn-fetch-blob (поддерживаемая версия react-native-fetch-blob), однако у меня не было никаких правил безопасности вместо c тестирования, Итак ...

Есть идеи для решения этой проблемы?

1 Ответ

1 голос
/ 23 января 2020

Да, вы догадались, ваш экземпляр FIREBASE не знает о том, что аутентификация выполняется firebase, поскольку firebase обрабатывает нативные аспекты, а FIREBASE - это просто JS. поэтому оба экземпляра имеют свою собственную жизнь и свои собственные перспективы с собственными атрибутами для идентификации пользователя и предоставления авторизации.

Чтобы решить эту проблему, попробуйте авторизовать пользователя либо с помощью vanilla JS SDK, либо используйте команду rn Огненная база для всей задачи. Я бы порекомендовал использовать react-native-firebase, он имеет хорошую поддержку всего стека Firebase. https://rnfirebase.io/docs/v5.x.x/storage/reference/storage

РЕДАКТИРОВАТЬ:

Vanilla JS Firebase SDK не следует использовать в мобильных приложениях, особенно когда он является нативным, поскольку firebase будет Относитесь к клиенту как к веб-клиенту, и в дальнейшем вы не сможете использовать все возможные мобильные вещи из firebase, такие как динамические c ссылки, pu sh уведомления и аналитика.

Надеюсь, это поможет! Ура!

...