From 0fd917ad49f1e7625daaca435174906b3aad760c Mon Sep 17 00:00:00 2001 From: Franco Date: Tue, 19 May 2020 16:19:28 -0300 Subject: [PATCH] Modified create user and image resize --- database.rules.json | 1 + functions/requests/routes/users.js | 123 ++++------------------------- src/firebase.js | 2 + src/state/actions/users.js | 112 +++++++++++++++----------- src/utils/index.js | 16 +++- 5 files changed, 100 insertions(+), 154 deletions(-) diff --git a/database.rules.json b/database.rules.json index 17eb6fd0..8c8a29fb 100644 --- a/database.rules.json +++ b/database.rules.json @@ -5,6 +5,7 @@ ".write": "auth !== null && auth.token.email_verified === true && ((auth.token.isAdmin === true && data.child('isAdmin').val() === false) || auth.uid === $user)", ".read": "auth !== null && auth.token.email_verified === true && ((auth.token.isAdmin === true && data.child('isAdmin').val() === false) || auth.uid === $user)" }, + ".write": "auth !== null && auth.token.email_verified === true && auth.token.isAdmin === true", ".read": "auth !== null && auth.token.email_verified === true && auth.token.isAdmin === true" } } diff --git a/functions/requests/routes/users.js b/functions/requests/routes/users.js index d5bbd2ac..e78b7a01 100644 --- a/functions/requests/routes/users.js +++ b/functions/requests/routes/users.js @@ -5,6 +5,7 @@ const Busboy = require('busboy'); const path = require('path'); const os = require('os'); const fs = require('fs'); +const uuid = require('uuid/v4'); const router = express.Router(); @@ -24,8 +25,8 @@ const uploadImageToBucket = async uploadedImage => { }); }; -const createUserAuth = async (email, password, isAdmin) => { - const { uid } = await admin.auth().createUser({ email, password }); +const createUserAuth = async (email, isAdmin) => { + const { uid } = await admin.auth().createUser({ email, password: uuid() }); await admin.auth().setCustomUserClaims(uid, { isAdmin @@ -34,114 +35,22 @@ const createUserAuth = async (email, password, isAdmin) => { return uid; }; -const createUserOnDb = async ( - name, - email, - location, - logoUrl, - userId, - createdAt, - isAdmin -) => { - const userData = { - name, - email, - location, - logoUrl, - createdAt, - isAdmin - }; - - const response = await admin - .database() - .ref(`users/${userId}`) - .set({ ...userData }); - - return response; -}; - -router.post('/', (request, response) => { - cors(request, response, () => { - const busboy = new Busboy({ headers: request.headers }); - - let uploadedImage = null; - - let fieldData = {}; - - busboy.on('field', (fieldName, value) => { - fieldData = { ...fieldData, [`${fieldName}`]: value }; - }); - - busboy.on('file', (fieldName, file, fileName, encoding, mimetype) => { - const filepath = path.join(os.tmpdir(), fileName); - - uploadedImage = { file: filepath, type: mimetype, fileName }; - - file.pipe(fs.createWriteStream(filepath)); - }); - - busboy.on('finish', async () => { - const { name, email, password, location, createdAt } = fieldData; - - const isAdmin = JSON.parse(fieldData.isAdmin); +router.post('/', async (request, response) => { + const { email, isAdmin } = request.body; - let id; - - try { - console.log('Creating user in auth and setting custom claims'); - id = await createUserAuth(email, password, isAdmin); - console.log('Created user auth and setting custom claims'); - } catch (error) { - console.error( - 'Error while creating user in auth and setting custom claims', - error - ); - return response.status(500).json({ error }); - } - - let logoUrl = null; - - if (uploadedImage) { - try { - console.log('Uploading logo to bucket'); - await uploadImageToBucket(uploadedImage); - logoUrl = `https://storage.googleapis.com/${bucket.name}/${uploadedImage.fileName}`; - console.log('Uploaded logo to bucket', logoUrl); - } catch (error) { - console.error('Error while uploading image to bucket', error); - return response.status(500).json({ error }); - } - } - - try { - console.log('Creating user'); - await createUserOnDb( - name, - email, - location, - logoUrl, - id, - createdAt, - isAdmin - ); - console.log('Created user'); - } catch (error) { - console.error('Error while creating user', error); - return response.status(500).json({ error }); - } + if (!email) { + return response.status(400).json({ error: { code: 'auth/invalid-email' } }); + } - return response.status(201).json({ - id, - name, - location, - email, - logoUrl, - isAdmin - }); - }); + let uid; + try { + uid = await createUserAuth(email, isAdmin); + } catch (error) { + console.error('Error while creating user', error); + return response.status(500).json({ error }); + } - busboy.end(request.rawBody); - }); + return response.status(200).json({ uid }); }); router.delete('/:id', async (request, response) => { diff --git a/src/firebase.js b/src/firebase.js index 2077382d..1b70131c 100644 --- a/src/firebase.js +++ b/src/firebase.js @@ -1,6 +1,7 @@ import firebase from 'firebase/app'; import 'firebase/database'; import 'firebase/auth'; +import 'firebase/storage'; const config = { apiKey: process.env.REACT_APP_FIRE_BASE_KEY, @@ -15,5 +16,6 @@ const config = { firebase.initializeApp(config); firebase.database(); +firebase.storage(); export default firebase; diff --git a/src/state/actions/users.js b/src/state/actions/users.js index edcb7106..f85d1bd7 100644 --- a/src/state/actions/users.js +++ b/src/state/actions/users.js @@ -113,63 +113,83 @@ export const createUser = ({ const userToken = await user.getIdToken(); - const body = new FormData(); - - if (file) { - const fileExtension = file.name.split('.')[1]; - - const fileName = `${uuid()}.${fileExtension}`; - - body.append('logo', file, fileName); + let response; + try { + response = await axios(userToken).post('/users', { email, isAdmin }); + } catch (error) { + const errorMessage = firebaseError(error.response.data.error.code); + toastr.error('', errorMessage); + return dispatch( + USERS_CREATE_USER_FAIL({ + error: errorMessage + }) + ); } - body.append('name', name); - body.append('location', location); - body.append('email', email); - body.append('password', uuid()); - body.append('createdAt', createdAt); - body.append('isAdmin', isAdmin); + const { uid } = response.data; + let path = null; + if (file) { + const storageRef = firebase.storage().ref(); - axios(userToken) - .post('/users', body) - .then(async response => { - const userCreated = response.data; + const fileExtension = file.name.split('.').pop(); - const actionCodeSettings = { - url: process.env.REACT_APP_LOGIN_PAGE_URL, - handleCodeInApp: true - }; - - try { - await firebase - .auth() - .sendSignInLinkToEmail(email, actionCodeSettings); - } catch (error) { - const errorMessage = firebaseError(error.response.data.error.code); - - return dispatch( - USERS_CREATE_USER_FAIL({ - error: errorMessage - }) - ); - } + const fileName = `${uid}.${fileExtension}`; - toastr.success('', 'User created successfully'); - return dispatch( - USERS_CREATE_USER_SUCCESS({ - user: userCreated - }) - ); - }) - .catch(error => { - const errorMessage = firebaseError(error.response.data.error.code); + const basePath = 'users/'; + try { + await storageRef.child(`${basePath}${fileName}`).put(file); + } catch (error) { + const errorMessage = firebaseError(error.code); toastr.error('', errorMessage); return dispatch( USERS_CREATE_USER_FAIL({ error: errorMessage }) ); - }); + } + path = `${basePath}${uid}_200x200.${fileExtension}`; + } + + try { + await firebase + .database() + .ref(`users/${uid}`) + .set({ + name, + email, + location, + logoUrl: path, + createdAt, + isAdmin + }); + } catch (error) { + const errorMessage = firebaseError(error.code); + toastr.error('', errorMessage); + return dispatch( + USERS_CREATE_USER_FAIL({ + error: errorMessage + }) + ); + } + + const actionCodeSettings = { + url: process.env.REACT_APP_LOGIN_PAGE_URL, + handleCodeInApp: true + }; + + try { + await firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings); + } catch (error) { + const errorMessage = firebaseError(error.code); + return dispatch( + USERS_CREATE_USER_FAIL({ + error: errorMessage + }) + ); + } + + toastr.success('', 'User created successfully'); + return dispatch(USERS_CREATE_USER_SUCCESS({ user: response.data })); }; }; diff --git a/src/utils/index.js b/src/utils/index.js index a9ef0016..66571067 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -11,7 +11,10 @@ export const FIREBASE_RESPONSE = { USER_DISABLED: 'auth/user-disabled', TOO_MANY_REQUESTS: 'auth/too-many-requests', EXPIRED_ACTION_CODE: 'auth/expired-action-code', - INVALID_ACTION_CODE: 'auth/invalid-action-code' + INVALID_ACTION_CODE: 'auth/invalid-action-code', + QUOTA_EXCEEDED_STORAGE: 'storage/quota-exceeded', + UNAUTHENTICATED_STORAGE: 'storage/unauthenticated', + UNAUTHORIZED_STORAGE: 'storage/unauthorized' }; export const firebaseError = error => { @@ -44,6 +47,17 @@ export const firebaseError = error => { errorMessage = 'The invitation link has expired, get in touch with your administrator'; break; + case FIREBASE_RESPONSE.QUOTA_EXCEEDED_STORAGE: + errorMessage = + 'Internal server error, get in touch with your administrator'; + break; + case FIREBASE_RESPONSE.UNAUTHENTICATED_STORAGE: + errorMessage = 'Unauthenticated, please authenticate and try again.'; + break; + case FIREBASE_RESPONSE.UNAUTHORIZED_STORAGE: + errorMessage = + 'Unauthoriez, you are not authorized to perform this action.'; + break; default: errorMessage = 'Unknown error, get in touch with your administrator'; }