Application for Managing Firebase Applications. Includes support for multiple environments and data migrations
Clone or download
prescottprue v0.7.0 (#68)
* fix(deps): update cypress-firebase to v0.0.5
* fix(actionRunner): fix an issue where some locked environments would not correctly disable the run button (actionRunner itself would still error out though)
Latest commit aec6df9 Nov 20, 2018
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.github v0.5.8 (#49) Aug 10, 2018
build Action Runner Tests (#65) Nov 16, 2018
functions v0.6.7 (#63) Nov 12, 2018
public v0.6.2 (#57) Sep 30, 2018
server Switched to Fireadmin application. Nov 10, 2017
src v0.7.0 (#68) Nov 20, 2018
test/e2e Action Runner Tests (#65) Nov 16, 2018
.babelrc v0.5.2 Jul 21, 2018
.eslintignore More E2E UI Tests + More Route Protection + Redux Persist (#51) Sep 12, 2018
.eslintrc v0.5.1 (#41) Jul 10, 2018
.firebaserc v0.6.1 (#55) Sep 14, 2018
.gitignore More E2E UI Tests + More Route Protection + Redux Persist (#51) Sep 12, 2018
.gitlab-ci.yml Remove build dependency from prod stages of gitlab config. Nov 16, 2018
CONTRIBUTING.md Switched to Fireadmin application. Nov 10, 2017
Dockerfile v0.5.8 (#49) Aug 10, 2018
LICENSE Switched to Fireadmin application. Nov 10, 2017
README.md v0.6.8 (#64) Nov 15, 2018
cloudbuild-e2e.yaml More E2E UI Tests + More Route Protection + Redux Persist (#51) Sep 12, 2018
cloudbuild.yaml v0.6.0 (#54) Sep 13, 2018
cypress.json More E2E UI Tests + More Route Protection + Redux Persist (#51) Sep 12, 2018
database.rules.json feat(tests): e2e tests for adding and deleting a project added Jul 17, 2018
firebase.json v0.6.2 (#57) Sep 30, 2018
firestore.indexes.json v0.5.7 (#47) Aug 4, 2018
firestore.rules v0.4.4 (#34) May 22, 2018
jsconfig.json Improved Cloud Functions Tests + Coverage (#52) Sep 11, 2018
package-lock.json v0.7.0 (#68) Nov 20, 2018
package.json v0.7.0 (#68) Nov 20, 2018
project.config.js More E2E UI Tests + More Route Protection + Redux Persist (#51) Sep 12, 2018
storage.rules v0.5.4 (#44) Aug 2, 2018

README.md

fireadmin

Build Status

License Code Style

Application for Managing Firebase Applications. Includes support for multiple environments and data migrations

Table of Contents

  1. Features
  2. Getting Started
  3. NPM Scripts
  4. Application Structure
  5. Run Your Own
  6. Requirements
  7. Before Starting
  8. Testing
  9. Cloud Functions Unit
  10. App E2E
  11. Deployment
  12. FAQ

Features

  • Manage multiple environments as a single project
  • Project Sharing (invite by email coming soon)
  • "Action Runner" for common project actions such as data migrations, and generating reports
  • Action Features include support for:
    • Multiple steps allowing many actions in one run
    • Backup phase (for easy backing up data before running your actions)
    • Custom logic (JS written in the browser with ESNext features like async/await)
  • Project level tracking of actions which have been run through Action Runner
  • Get/Set CORS Config of Storage Buckets
  • Testing for React App (Cypress) and Cloud Functions (Mocha)

coming soon

  • Support for copying Single Firestore Document in Copy Action
  • Map action - for mapping each item in a collection both on RTDB and Firestore
  • Authorized Google API Request Panel
  • Invite new users by email
  • User manager (including role assignment)
  • Data Viewer

Interested in adding a feature or contributing? Open an issue or reach out over gitter.

Getting Started

Checkout the hosted version available at fireadmin.io. After you become more familiar, feel free to run your own by pulling this source and proceeding to the run your own section.

NPM Scripts

While developing, you will probably rely mostly on npm start; however, there are additional scripts at your disposal:

npm run <script> Description
start Serves your app at localhost:3000 and displays Webpack Dashboard
start:simple Serves your app at localhost:3000 without Webpack Dashboard
start:dist Builds the application to ./dist and Serves it at localhost:3000 using firebase serve
functions:start Runs Functions locally using firebase functions:shell
functions:build Builds Cloud Functions to ./functions/dist
functions:test Runs Functions Unit Tests with Mocha
build Builds the application to ./dist
test Runs E2E Tests with Cypress. See testing
lint Lints the project for potential errors
lint:fix Lints the project and fixes all correctable errors

Husky is used to enable prepush hook capability. The prepush script currently runs eslint, which will keep you from pushing if there is any lint within your code. If you would like to disable this, remove the prepush script from the package.json.

Application Structure

├── bin                      # Scripts called from the command line
│   └── firebase-extra.js    # Script called by tests to seed/clear Firebase
├── build                    # All build-related configuration
│   └── webpack.config.js    # Environment-specific configuration files for webpack
├── server                   # Express application that provides webpack middleware
│   └── main.js              # Server application entry point
├── functions                # Cloud Functions (uses Cloud Functions for Firebase)
│   └── index.js             # Functions entry point
├── src                      # Application source code
│   ├── index.html           # Main HTML page container for app
│   ├── main.js              # Application bootstrap and rendering
│   ├── normalize.js         # Browser normalization and polyfills
│   ├── components           # Global Reusable Presentational Components
│   ├── containers           # Global Reusable Container Components
│   ├── layouts              # Components that dictate major page structure
│   │   └── CoreLayout       # Global application layout in which to render routes
│   ├── routes               # Main route definitions and async split points
│   │   ├── index.js         # Bootstrap main application routes with store
│   │   └── Home             # Fractal route
│   │       ├── index.js     # Route definitions and async split points
│   │       ├── assets       # Assets required to render components
│   │       ├── components   # Presentational React Components
│   │       ├── container    # Connect components to actions and store
│   │       ├── modules      # Collections of reducers/constants/actions
│   │       └── routes **    # Fractal sub-routes (** optional)
│   ├── static               # Static assets
│   ├── store                # Redux-specific pieces
│   │   ├── createStore.js   # Create and instrument redux store
│   │   └── reducers.js      # Reducer registry and injection
│   └── styles               # Application-wide styles (generally settings)
├── test                     # App Tests
│   └── e2e                  # App End To End tests
├── .firebaserc              # Firebase project settings (including settings for CI deployment)
├── cypress.json             # Cypress E2E Testing settings
├── database.rules.json      # Firebase Real Time Database Rules
├── firebase.json            # Firebase resource settings (including which folders are deployed)
├── firestore.indexes.json   # Firestore Indexes
├── firestore.rules          # Firestore Database Rules
├── project.config.js        # Project configuration settings
└── storage.rules            # Cloud Storage Rules

Run Your Own

Requirements

Before Starting

  1. Make sure you have enabled billing on your Firebase account - external API communication requires setting up a payment method (you are only charged based on usage)
  2. Create an account on Algolia - Create a new app, you will need the API keys later
  3. Install Firebase Command Line Tools: npm i -g firebase-tools

Local Environment Setup

  1. Install dependencies: npm install

  2. Look for a src/config.js file. If one doesn't exist, create it to look like so (this is generated using firebase-ci in CI environments):

    export const version = "0.*.*"; // matches package.json when using firebase-ci in CI environment
    
    export const env = "local"; // matches branch/project alias when using firebase-ci in CI environment
    
    // Get from Auth Tab with Firebase's Console
    // matches branch/project settings when using firebase-ci in CI environment
    export const firebase = {
      apiKey: "<- api key ->",
      authDomain: "<- auth domain ->",
      databaseURL: "<- database URL ->",
      projectId: "<- project ID ->",
      storageBucket: "<- storageBucket ->",
      messagingSenderId: "<- message sender ID ->",
    };
    
    export const reduxFirebase = {
      userProfile: "users",
      enableLogging: false,
      updateProfileOnLogin: true,
      useFirestoreForProfile: true,
    };
    
    // Google Analytics Tracking ID (leave blank for no analytics)
    export const analyticsTrackingId = "<- your analytics tracking id ->";
    
    // Stackdriver client side error reporting (leave blank for no client side error reporting)
    export const googleApis = {
      apiKey: "<- your API Key for Google APIs ->",
    };
    
    // Algolia project info (for searching of User's Public Info and Public Templates)
    export const algolia = {
      appId: "<- your algolia app id ->",
      apiKey: "<- your algolia apiKey ->",
    };
    
    export default {
      version,
      env,
      firebase,
      reduxFirebase,
      analyticsTrackingId,
      googleApis,
      algolia
    }
  3. Create functions/.runtimeconfig.json file that looks like so:

    {
      "algolia": {
        "api_key": "<- your API KEY ->",
        "app_id": "<- your Algolia APP ID ->"
      },
      "gmail": {
        "email": "<- gmail account for sending invite emails ->",
        "password": "<- password for ^ email ->"
      },
      "encryption": {
        "password": "<- your own made up encryption password for service accounts -> "
      }
    }
  4. Set Functions config variables to match the file you just made (for the deployed version of your functions):

    Required Variables

    firebase functions:config:set algolia.api_key="<- your algolia api key ->" algolia.api_key="<- your algolia api key ->"\
    encryption.password="somePassword"

    Optional

    firebase functions:config:set gmail.email="<- inviter gmail account ->" gmail.password="<- password of inviter account ->"
  5. Build Project: npm run build

  6. Deploy to Firebase: firebase deploy (deploys, Cloud Functions, Rules, and Hosting)

  7. Start Development server: npm start NOTE: You can also use npm run start:dist to test how your application will work when deployed to Firebase

  8. View the deployed version of the site by running firebase open hosting:site

Deployment

CI Deploy (recommended)

Note: Config for this is located within .gitlab-ci.yml. firebase-ci has been added to simplify the CI deployment process by getting settings from the .firebaserc. All that is required is providing authentication with Firebase:

  1. Have at least two Firebase projects to ready to use, one for each environment (staging and production)
  2. Replace info within .firebaserc under both the projects and ci sections
  3. Replace environment settings within .gitlab-ci.yml with your own. This will make the "Operations" tab of Gitlab point to your environment URLs.
  4. Login: firebase login:ci to generate an authentication token. This token will be used to give the CI provider rights to deploy on your behalf. Settings are provided for Gitlab, but any CI provider can be used.
  5. Set FIREBASE_TOKEN environment variable within Gitlab-CI environment variables
  6. Add the following environment variables to Gitlab-CI's variables (within /settings/ci_cd):
    FIREBASE_TOKEN // Used to deploy to Firebase (token generated in last step)
    /* Stage Vars */
    STAGE_FIREBASE_API_KEY // apiKey staging project (from Firebase Auth Tab)
    STAGE_ALGOLIA_APP_ID // algolia app_id of staging project
    STAGE_ALGOLIA_BROWSER_KEY // algolia browser_key of staging project
    /* Prod Vars */
    PROD_FIREBASE_API_KEY // apiKey staging project (from Firebase Auth Tab)
    PROD_ALGOLIA_APP_ID // algolia app_id of staging project
    PROD_ALGOLIA_BROWSER_KEY // algolia browser_key of staging project
    /* Optional */
    SENTRY_DSN // Sentry DSN for error tracking
    STAGE_GOOGLE_API_KEY // API Key for Stackdriver error logging (can use firebase apiKey)
    PROD_GOOGLE_API_KEY // API Key for Stackdriver error logging (can use firebase apiKey)
  7. Run a build on Gitlab-CI by pushing code to your Git remote (most likely Github)

For more options on CI settings checkout the firebase-ci docs.

Manual deploy

  1. Make sure you have created a src/config.js file as mentioned above
  2. Initialize project with firebase init then answer:
  • What file should be used for Database Rules? -> database.rules.json
  • What do you want to use as your public directory? -> build
  • Configure as a single-page app (rewrite all urls to /index.html)? -> Yes
  • What Firebase project do you want to associate as default? -> your Firebase project name
  1. Build Project: npm run build
  2. Confirm Firebase config by running locally: firebase serve
  3. Deploy to firebase: firebase deploy NOTE: You can use firebase serve to test how your application will work when deployed to Firebase, but make sure you run npm run build first.

Testing

NOTE: If you have setup CI deployment, E2E tests and Unit Tests can automatically run against your staging environment before running the production build.

Cloud Functions Unit Tests

Cloud Functions Unit tests are written in Mocha with code coverage generated by Istanbul. These tests cover "backend functionality" handled by Cloud Functions by stubbing the functions environment (including dependencies).

Run Locally
  1. Go into the functions folder: cd functions
  2. Confirm you have dependencies installed: npm i
  3. Run unit tests: npm test
  4. To also generate coverage while testing, run npm run test:cov

App E2E Tests

End to End tests are done using Cypress and they live within the test/e2e folder. These tests cover UI functionality and are run directly on the hosted environment of Fireadmin. Application end to end tests are run automatically in Gitlab-CI the after deploying to the staging environment before deploying to production.

Run Locally
  1. Create a service account within the Firebase console
  2. Save the service account as serviceAccount.json within the root of the project
  3. Get the UID of the user that you want to use while testing from the Authentication tab of the Firebase console to
  4. Create a test/e2e/config.json with the following format:
    {
      "TEST_UID": "<- user account's UID ->",
      "FIREBASE_PROJECT_ID": "<- your projectId ->",
      "FIREBASE_API_KEY": "<- your firebase apiKey ->"
    }
  5. Run npm run start:dist. This will:
    1. Build the React app to the dist folder
    2. Host the build app on a local server using firebase serve
  6. In a different terminal tab, run npm run test:ui. This will:
    1. Create test environment configuration (includes JWT created using service account)
    2. Open Cypress's local test runner UI where you can run single tests or all tests

NOTE: npm run start:dist is used to start the local server in the example above for speed while running all tests. If you are developing the application while re-running a single test, or just a few, you can use npm run start instead.

FAQ

  1. Why node 8.11.3 instead of a newer version? Cloud Functions runtime supports 6 or 8, which is why that is what is used for the CI build version. This will be switched when the functions runtime is updated
  2. Uploading service accounts? Where do they go and how are my service accounts stored? When uploading a service account, it first goes to a Google Cloud Storage Bucket which has security rules and does not have CORS access. The copyServiceAccountToFirestore Cloud Function converts it into an encrypted string, stores it within Firestore, then removes the original file from Cloud Storage. Firestore rules keep anyone that is not a collaborator on your project using or reading the service account. Since it is associated with a specific environment, you can then limit access to what can be done with it right in the Users/Permissions tab of Fireadmin.