DEV Community

Cover image for RN: Amplify Auth & Storage
Mike Oristian
Mike Oristian

Posted on

RN: Amplify Auth & Storage

I'm trying to understand how to configure AWS Amplify React Native projects so that the <S3Image/> and <S3Album/> components work properly. I thought I'd write a blog post with questions and then update it with the answers I get from the Amplify community.

It's a simple Profile screen I'm trying to manage, with a list of all the recent uploads to the S3 bucket. I'd like to know I have the permission configured properly for upload and viewing, then explore how I should store the S3 Image pathways (or keys) in DataStore such that I have a foolproof way to display the current user's profile picture as well as any other profile's picture (even if they upload to a 'protected' directory)

I've set this storage up with the amplify-cli but I'd like to know how to double check that CORS and the Bucket's policies are correctly assigned for access via the app's Amplify toolkit.

import React, { useState, useEffect } from 'react';
import { View, Text, Image, Button, ActivityIndicator } from 'react-native';

import Amplify from '@aws-amplify/core';
import Auth from '@aws-amplify/auth';
import { Storage } from 'aws-amplify'
import { S3Image, S3Album } from 'aws-amplify-react-native'
import config from '../../aws-exports';
Amplify.configure(config);

import { 
launchCamera, 
launchImageLibrary } from 'react-native-image-picker';

import defaultAvatar from '../assets/images/defaultAvatar.png'


Amplify.configure({
    Storage: {
        AWSS3: {
            bucket: 'XXXXXXXXXXX-staging',
            region: 'us-west-2',
        }
    },
    Auth: {
        region: 'us-west-2', Region
        userPoolId: 'YYYYYYYYYYYY'
    },

    Analytics: {
        disabled: true,
    }
})
Enter fullscreen mode Exit fullscreen mode

Here is my main component below - and here are my questions

  • I'm able to print out my currentAuthenticatedUser's attributes, but how is this user passed to the S3Image call and the Storage call?
  • I'm getting 403 errors for the most part, but I can see the images getting uploaded, just not shown on the useEffect retrieval
  • What are the checklists to run through to ensure CORS and Bucket Policy (json) is set correctly for access?
  • Should we be importing from @aws-amplify or 'aws-amplify' with deconstructors ({Auth})
  • Lastly, if Storage is configured at {level: 'protected'} then how will other users be able to use the key I need to store in DataStore
const Profile = ({ navigation }) => {
    const [avatar, setAvatar] = useState(defaultAvatar);
    const [avatarFileName, setAvatarFileName] = useState('')
    const [allUploads, setAllUploads] = useState([])

    const handlePicker = () => {
        launchImageLibrary({ mediaType: 'photo' }, (response) => {
            console.log('Response = ', response);

            if (response.didCancel) {
                console.log('User cancelled image picker');
            } else if (response.error) {
                console.log('ImagePicker Error: ', response.error);
            } else if (response.customButton) {
                console.log('User tapped custom button: ', response.customButton);
            } else {
                setAvatar({ uri: response.uri });
                setAvatarFileName(response.fileName);
            }
        });
    };

    const uploadImageAsync = async (pickerResult) => {
        try {
            console.log(avatar)
            const profileFile = await fetch(avatar.uri);
            const blob = await profileFile.blob();
            console.log('*** gonna post ' + avatarFileName)
            Storage.put(avatarFileName, blob)
                .then(result => console.log(result))
                .catch(err => console.log(err))
        }
        catch (e) {
            console.log('Something errored ' + e)

        }
    }

    useEffect(() => {
        Storage.list('', { level: 'protected' })
            .then(results => {
                console.log('s3 list callback')
                setAllUploads(results);
                console.log(results)
            })

        Auth.currentAuthenticatedUser()
            .then(user => {
                console.log(user.attributes.phone_number)
            })
    }, [])


    return (
        <>
            <View style={{ justifyContent: 'center', flexDirection: 'row' }}>
                {allUploads && allUploads.map((upload, i) => (
                    <S3Image key={i} imgKey={upload.key} style={{ width: 100, height: 100 }} />
                ))}
            </View>
            <View>
                <Image
                    source={avatar}
                    PlaceholderContent={<ActivityIndicator />}
                    style={{ width: 400, height: 400 }}
                />
                <Button title='Choose Picture' onPress={() => { handlePicker() }} />
                <Button title='Upload Picture' onPress={() => { uploadImageAsync(avatar) }} />

            </View>
        </>
    )
}

export default Profile;
Enter fullscreen mode Exit fullscreen mode

Thanks in advance for taking a look and helping me clarify the proper way to use these components in React Native

Top comments (0)