Skip to content

Commit 551ad86

Browse files
committed
fixed conflicts with master
2 parents 51e51ed + 63181a7 commit 551ad86

28 files changed

Lines changed: 970 additions & 1656 deletions

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ REACT_APP_FIRE_BASE_APP_ID = ''
88
REACT_APP_FIRE_BASE_MEASURMENT_ID = ''
99
REACT_APP_CLOUD_FUNCTIONS_REST_API = '<FIREBASE_CLOUD_FUNCTIONS_URL>/requestsApp'
1010
REACT_APP_LOGIN_PAGE_URL = 'http://localhost:3000/login'
11+
REACT_APP_FIRE_BASE_STORAGE_API = 'https://firebasestorage.googleapis.com/v0/b/${REACT_APP_FIRE_BASE_STORAGE_BUCKET}'

.eslintignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
build/*
2-
functions/*
1+
build/*

.firebaserc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"projects": {
33
"production": "react-firebase-admin-eeac2",
4-
"staging": "react-firebase-admin-eeac2"
4+
"staging": "react-firebase-admin-eeac2",
5+
"default": "react-firebase-admin-eeac2"
56
}
67
}

README.md

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Boilerplate with React ⚛️ and Firebase 🔥designed to quickly spin up a ful
1515
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
1616
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
1717

18+
1819
- [What is this?](#what-is-this)
1920
- [Why should I use it?](#why-should-i-use-it)
2021
- [Features](#features)
@@ -57,6 +58,9 @@ Boilerplate with React ⚛️ and Firebase 🔥designed to quickly spin up a ful
5758
- [How to translate a Text with a variable](#how-to-translate-a-text-with-a-variable)
5859
- [How to internationalize a Date](#how-to-internationalize-a-date)
5960
- [How to add your language on DatePicker](#how-to-add-your-language-on-datepicker)
61+
- [File Upload](#file-upload)
62+
- [Image Resize](#image-resize)
63+
- [Storage Rules](#storage-rules)
6064
- [Contributors](#contributors)
6165
- [License](#license)
6266

@@ -136,17 +140,15 @@ React Firebase Admin is our in-house admin dashboard boilerplate, used in many o
136140

137141
- [Express](https://github.com/expressjs/express) (★ 47.5k) fast, unopinionated, minimalist web framework for node.
138142
- [Cors](https://github.com/expressjs/cors) (★ 4.4k) Node.js CORS middleware.
139-
- [Nodemailer](https://github.com/nodemailer/nodemailer) (★ 12.2k) send e-mails with Node.js.
140143
- [Firebase-admin](https://github.com/firebase/firebase-admin-node) (★ 790) Firebase Admin Node.js SDK.
141144
- [Firebase-functions](https://github.com/firebase/firebase-functions) (★ 658) Firebase SDK for Cloud Functions.
142145
- [@google-cloud/storage](https://github.com/googleapis/nodejs-storage) (★ 421) Node.js client for Google Cloud Storage.
143146
- [Firebase-function-tools](https://github.com/TarikHuber/react-most-wanted) (★ 780) a tool for naming and loading our Cloud Functions.
144147
- [Cookie-parser](https://github.com/expressjs/cookie-parser) (★ 1.4k) parse HTTP request cookies.
145148
- [Uuid](https://github.com/uuidjs/uuid) (★ 8.7k) generate RFC-compliant UUIDs in JavaScript.
146-
- [Busboy](https://github.com/mscdex/busboy) (★ 1.8k) a streaming parser for HTML form data for Node.js.
147-
- [Sharp](https://github.com/lovell/sharp) (★ 15.8k) high performance Node.js image processing.
148149
- [Glob](https://github.com/isaacs/node-glob) (★ 6.2k) glob functionality for Node.js.
149150
- [Fs-extra](https://github.com/jprichardson/node-fs-extra) (★ 6.6k) Node.js: extra methods for the fs object like copy(), remove(), mkdirs().
151+
- [Resize Image](https://github.com/firebase/extensions/tree/master/storage-resize-images) (★ 372) Firebase Extension to create resized versions of images uploaded to Cloud Storage.
150152

151153
## Prerequisites
152154

@@ -174,7 +176,7 @@ Run the following commands in the root of the repository:
174176
- `npm install -g firebase-tools`
175177
- `firebase init`
176178

177-
Select the firebase project you created in the previous step, when prompted select the services you want to setup and check **_Database_**, **_Functions_** and **_Hosting_**.
179+
Select the firebase project you created in the previous step, when prompted select the services you want to setup and check **_Database_**, **_Functions_**, **_Hosting_** and **_Storage_**.
178180

179181
**_Database_**:
180182

@@ -201,6 +203,9 @@ You'll get prompted to enter the path to you service account key file. To genera
201203

202204
You'll need to enter the **_email_** and **_password_** for the admin account of the admin dashboard. With this in place, you've successfully created your admin account for the dashboard.
203205

206+
**_Storage_**
207+
-For the file we should use for the Storage Rules select storage.rules.
208+
204209
### Setting up the React frontend
205210

206211
Run the following commands in the root of the repository (Using Node v12.15.0 or higher ):
@@ -569,6 +574,53 @@ const date = Date.now();
569574
- Add another **registerLocale** with your language as the first parameter and the import from `date-fns` as second parameter.
570575
- Place your language with its date format on **dateFormat**.
571576
577+
## File Upload
578+
579+
For file upload, we used the [Firebase Client](https://firebase.google.com/docs/storage/web/upload-files?authuser=1#upload_files) together with **Firebase Storage** for our storage needs. We store the users profile image in a subfolder named `/users`.
580+
581+
### Image Resize
582+
583+
We use [Resize Image](https://github.com/firebase/extensions/tree/master/storage-resize-images) for resizing every image uploaded to the storage.
584+
Every image uploaded to the storage is resized to our size preference (`200px x 200px`).
585+
586+
**Setting your image resize**
587+
588+
If you want to install it from the cmd, you can execute:
589+
590+
```javascript
591+
firebase ext:install storage-resize-images --project=projectId
592+
```
593+
594+
Wih your own `projectId`
595+
596+
<ol>
597+
<li>Go to your Firebase Proyect on <a href= "https://console.firebase.google.com/u/1/">Firebase Console</a> </li>
598+
<li>Select extensions from the sidebar</li>
599+
<li>Search for Resize Images extension</li>
600+
<li>Click install on the extension</li>
601+
<li>On extension configuration set sizes of resized images to 200x200 and the deletion of original file to true</li>
602+
<li>Click on install extension</li>
603+
</ol>
604+
605+
In case you do not want to upload a resized version and upload the original file, you should avoid step **5**.
606+
607+
### Storage Rules
608+
609+
To make images reachable, we needed to set our storage rules to allow users to `write` on the storage made for the user logo, only if they are authenticated, but they can always `read`, this was set for saving the user´s logo path on the database.
610+
611+
**Should look like this**
612+
613+
```javascript
614+
service firebase.storage {
615+
match /b/{bucket}/o {
616+
match /users/{imageId} {
617+
allow write: if request.auth!=null;
618+
allow read: if true;
619+
}
620+
}
621+
}
622+
```
623+
572624
## Contributors
573625
574626
We'd like to thank these awesome people who made this whole thing happen:

database.rules.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
"rules": {
33
"users": {
44
"$user": {
5-
".write": "auth !== null && auth.token.email_verified === true && data.child('tenant').val() === auth.token.tenant && ((auth.token.isAdmin === true && data.child('isAdmin').val() === false) || auth.uid === $user)",
6-
".read": "auth !== null && auth.token.email_verified === true && data.child('tenant').val() === auth.token.tenant && ((auth.token.isAdmin === true && data.child('isAdmin').val() === false) || auth.uid === $user)"
5+
".write": "auth !== null && auth.token.email_verified === true && ((auth.token.isAdmin === true && data.child('isAdmin').val() === false) || auth.uid === $user)",
6+
".read": "auth !== null && auth.token.email_verified === true && ((auth.token.isAdmin === true && data.child('isAdmin').val() === false) || auth.uid === $user)"
77
},
8-
".read": "auth !== null && auth.token.email_verified === true && auth.token.isAdmin === true && query.orderByChild === 'tenant' && query.equalTo === auth.token.tenant",
9-
".indexOn": ["tenant"]
8+
".write": "auth !== null && auth.token.email_verified === true && auth.token.isAdmin === true",
9+
".read": "auth !== null && auth.token.email_verified === true && auth.token.isAdmin === true"
1010
}
1111
}
1212
}

firebase.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,8 @@
1515
"destination": "/index.html"
1616
}
1717
]
18+
},
19+
"storage": {
20+
"rules": "storage.rules"
1821
}
1922
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const functions = require('firebase-functions');
2+
const admin = require('firebase-admin');
3+
4+
export default functions.database
5+
.ref('users/{uid}')
6+
.onDelete((snapshot, context) => {
7+
const { uid } = context.params;
8+
return admin.auth().deleteUser(uid);
9+
});
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const functions = require('firebase-functions');
2+
const admin = require('firebase-admin');
3+
4+
export default functions.database
5+
.ref('/users/{uid}')
6+
.onUpdate((change, context) => {
7+
const before = change.before.val();
8+
const after = change.after.val();
9+
const { isAdmin } = after;
10+
11+
if (before.isAdmin === isAdmin) {
12+
return null;
13+
}
14+
15+
const { uid } = context.params;
16+
17+
return admin.auth().setCustomUserClaims(uid, {
18+
isAdmin
19+
});
20+
});

0 commit comments

Comments
 (0)