diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index bd8460ee7..000000000 --- a/.dockerignore +++ /dev/null @@ -1,4 +0,0 @@ -.git -build -node_modules -npm-debug.log* \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index a435497b9..000000000 --- a/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -# FROM mhart/alpine-node:13 - -# WORKDIR /usr/src/app - -# COPY /package*.json ./ - -# RUN npm install - -# COPY . . - -# WORKDIR /usr/src/app/client - -# COPY /client/package*.json ./ - -# RUN npm install - -# COPY /client . - -# RUN npm run build - -# WORKDIR /usr/src/app - -# CMD [ "npm", "start" ] diff --git a/README.md b/README.md index 5468e3175..059dd2cb5 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,12 @@ This is an ambitious project to create a system that will help us measure our hu ## Project Context -We are currently in the initial planning phase after delivering a prototype to the organization's leadership. Our priorities are laying out a feature roadmap for beta and beyond, and recruiting a team of dedicated members to build the product. Time is of the essence, as each Hack Night is a new opportunity to garner valuable data which, in return, supports the organization and it's members. +We are currently in the initial planning phase after delivering a prototype to the organization's leadership. Our priorities are laying out a feature roadmap for beta and beyond, and recruiting a team of dedicated members to build the product. Time is of the essence, as each Hack Night is a new opportunity to garner valuable data which, in return, supports the organization and it's members. ## Technologies This is a Full Stack web app, built with: + - [React](https://reactjs.org/docs/getting-started.html) - [Node](https://nodejs.org/en/) / [Express](https://expressjs.com/en/starter/installing.html) - [MongoDB](https://docs.mongodb.com/manual/tutorial/getting-started/) @@ -18,7 +19,7 @@ This is a Full Stack web app, built with: ## How to contribute -Head over to the Issues tab and see if you'd like to contribute. +Head over to the Issues tab and see if you'd like to contribute. If this seems like a project you'd like to dedicate your time to, reach out to the leads on Slack or at one of our weekly Hack Nights. @@ -36,7 +37,7 @@ This section discusses some tips and best practices for working with Git. 1. From the `VRMS` repository, create a Pull Request which asks `VRMS` to pull changes from your fork into the main repository. -1. After the owner of the `VRMS` repository approves and merges your Pull Request, your changes will be live on the website. +1. After the owner of the `VRMS` repository approves and merges your Pull Request, your changes will be live on the website. ### Forking and cloning the repository with proper security @@ -50,7 +51,7 @@ Once you have accepted the GitHub invite (via email or in your GitHub notificati 1. Setup two factor authentication on your account https://github.com/hackforla/governance/issues/20 -These steps are manditory in order to contribute to all HackforLA projects. +These steps are manditory in order to contribute to all HackforLA projects. #### Step 2: Fork the repository @@ -120,7 +121,7 @@ We prefer that you work on a branch name that relates to the issue you're workin The format should look like the scheme above where `140` is the issue number in GitHub, and the words are a brief description of the issue. -No law of physics will break if you don't adhere to this scheme but laws of git will break if you add spaces in the branch name. +No law of physics will break if you don't adhere to this scheme but laws of git will break if you add spaces in the branch name. ### Incorporating changes from upstream @@ -138,35 +139,49 @@ git fetch vrms git reset --hard vrms/master ``` -## Get up and running +## Get up and running (locally) 1. Have [Node](https://nodejs.org/en/download/) and NPM installed locally: - - Verify with `node -v` and `npm -v` respectively. + + - Verify with `node -v` and `npm -v` respectively. 1. Install [Yarn](https://classic.yarnpkg.com/en/docs/install/#mac-stable): an improved package manager - - Verify with `yarn --version` -1. Verify that you have the git remote repositories configured: - - Verify that the output of `git remote -v` shows your local repo as origin and the upstream vrms repo. + - Verify with `yarn --version` + +1. Verify that you have the git remote repositories configured: + + - Verify that the output of `git remote -v` shows your local repo as origin and the upstream vrms repo. 1. Install the node packages needed in each directory: - - `cd vrms/` and run `yarn install` - - `cd client` and run `yarn install` - - `cd ../backend` and run `yarn install` + + - `cd vrms/` and run `yarn install` + - `cd client` and run `yarn install` + - `cd ../backend` and run `yarn install` 1. Add your required environment variables for the frontend and backend directories: - - `touch vrms/backend/.env` - - `touch vrms/client/.env` - - Then paste the content from the [document](https://docs.google.com/document/d/1yDF6UmyO-MPNrl3y_Mw0mkm_WaixlSkXzWbudCzHXDY/edit?usp=sharing). It is accessible for the project team members only. - - *Please note that the `ports` for the frontend and backend are set in this location* -1. Take a second to review the `app.js` and `server.js` files in the `vrms/backend` folder. These two files are a blueprint for the back end, so please familiarize yourself with it. You'll see folders for the database collection models, routes for the API, and a config file which loads the necessary environment variables. + - `touch vrms/backend/.env` + - `touch vrms/client/.env` + - Then paste the content from the [document](https://docs.google.com/document/d/1yDF6UmyO-MPNrl3y_Mw0mkm_WaixlSkXzWbudCzHXDY/edit?usp=sharing). It is accessible for the project team members only. + - _Please note that the `ports` for the frontend and backend are set in this location_ + +1. Take a second to review the `app.js` and `server.js` files in the `vrms/backend` folder. These two files are a blueprint for the back end, so please familiarize yourself with it. You'll see folders for the database collection models, routes for the API, and a config file which loads the necessary environment variables. 1. Start the local development servers (frontend & backend). - - Navigate to the root of the application `vrms/` and run `npm run dev` + - Navigate to the root of the application `vrms/` and run `npm run dev` You should now have a live app. Happy hacking. +## Get up and running (Docker alternative) + +1. [Download docker](https://docs.docker.com/get-docker/) to your machine. +1. Start docker locally. +1. Navigate to the root directory. +1. Run `docker-compose build`. +1. Run `docker-compose up`. +1. Navigate to the port for the NGINX container listed in the docker-compose.yml file. + ## Running Tests The VRMS application has a variety of tests written for the application. Review the `package.json` file in any directory @@ -178,19 +193,25 @@ To run all of the tests run `npm run test:all` from the root folder. The application uses MongoDB and the team has a few databases for differing environments. Below are instructions on how to connect to the different databases used for development. -1. Staging test database: This database is maintained by the team. Post in the #vrms-dev channel to see who has access if you have any issues. This db has data useful for developming - 1. Navigate to the [Get up and running](#get-up-and-running) section and find the credentials link. - 1. Add the mongoDB credential listed in the `DATABASE_URL` variable to your `backend/.env` file. +1. Shared Staging Development database: This database is maintained by the team. Post in the #vrms-dev channel to see who has access if you have any issues. This db has data useful for developming -1. Localhost test database: Create your own database on your laptop and connect to it. This database will be empty and you will need to add your own data. follow this [tutorial](https://zellwk.com/blog/local-mongodb/) for an in depth look on how to setup a local copy of mongodb. - 1. Download mongoDB. - 1. Setup a local mongoDB cluster. - 1. Get the connection string. - 1. Add your localhost connection string to the `DATABASE_URL` variable to your `backend/.env` file. + 1. Navigate to the [Get up and running](#get-up-and-running) section and find the credentials link. + 1. Add the mongoDB credential listed in the `DATABASE_URL` variable to your `backend/.env` file. + 1. The environment variable should start with `mongodb+srv://editor:SHARED_DB_URL`. -1. Test case in-memory-MongoDB: The unit tests and integration tests create and remove an in memory database on each test run. You should not need to connect to these test databases. See the `backend/README.md` for more information. +1. Localhost Development database: This database requires that you setup MongoDB on your local machine. See the [tutorial](https://zellwk.com/blog/local-mongodb/) for an in depth look on how to do this. + 1. Download mongoDB. + 1. Setup a local mongoDB cluster. + 1. Get the connection string. + 1. Add your localhost connection string to the `DATABASE_URL` variable to your `backend/.env` file. + 1. If you are running the application directly on your machine, then your environment variable should start with `mongodb://localhost:27017/YOUR_DB_NAME`. + 1. If you are running the application using a docker container, then your environment variable should start with `mongodb://host.docker.internal:27017/YOUR_DB_NAME`. + +1. To create a local copy of a DB from a remote url, then use the backup script as seen in `utils/local_db_backup.sh`. + +1. Test case in-memory-MongoDB: The unit tests and integration tests create and remove an in memory database on each test run. You should not need to connect to these test databases. See the `backend/README.md` for more information. -### Licensing *WIP* +### Licensing _WIP_ -Details about the project's open source status below: +Details about the project's open source status below: diff --git a/backend/.dockerignore b/backend/.dockerignore new file mode 100644 index 000000000..ccfdb18a1 --- /dev/null +++ b/backend/.dockerignore @@ -0,0 +1,6 @@ +.git +.dockerignore +docker-compose*.yml +npm-debug.log* +Dockerfile +node_modules diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 000000000..a613c11c2 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,23 @@ +FROM node:14.11.0 AS development + +RUN mkdir /srv/backend && chown node:node /srv/backend + +WORKDIR /srv/backend + +USER node + +COPY --chown=node:node package.json yarn.lock ./ + +RUN yarn install --silent + +RUN mkdir -p node_modules + +FROM node:14.11.0-slim AS production + +USER node + +WORKDIR /srv/backend + +COPY --from=development --chown=root:root /srv/backend/node_modules ./node_modules + +COPY . . diff --git a/backend/app.js b/backend/app.js index fea4dd01e..a71513857 100644 --- a/backend/app.js +++ b/backend/app.js @@ -57,11 +57,7 @@ app.use("/api/projects", projectsRouter); app.use("/api/recurringevents", recurringEventsRouter); app.use("/api/projectteammembers", projectTeamMembersRouter); app.use("/api/slack", slackRouter); -app.use("/api/auth", authRouter); -const CLIENT_BUILD_PATH = path.join(__dirname, "../client/build"); - -// Serve static files from the React frontend app -app.use(express.static(path.join(CLIENT_BUILD_PATH))); +app.use('/api/auth', authRouter); // 404 for all non-defined endpoints. app.get("*", (req, res) => { diff --git a/client/.dockerignore b/client/.dockerignore index 5171c5408..ccfdb18a1 100644 --- a/client/.dockerignore +++ b/client/.dockerignore @@ -1,2 +1,6 @@ +.git +.dockerignore +docker-compose*.yml +npm-debug.log* +Dockerfile node_modules -npm-debug.log \ No newline at end of file diff --git a/client/Dockerfile b/client/Dockerfile index 558b621f4..4f1d6ddd1 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -1,10 +1,27 @@ -# FROM mhart/alpine-node:13 +FROM node:14.11.0 AS development -# WORKDIR /usr/src/app/ +RUN mkdir /srv/client && chown node:node /srv/client -# COPY package*.json ./ -# RUN npm ci -qy +WORKDIR /srv/client + +USER node + +COPY --chown=node:node package.json yarn.lock ./ + +RUN yarn install --silent + +RUN mkdir -p node_modules + +# # TODO: Fix production application. We are currently serving static frontend assets from the backend. +# FROM node:14.11.0-slim AS production + +# USER node + +# WORKDIR /srv/client + +# COPY --from=development --chown=root:root /srv/backend/.env /srv/backend +# COPY --from=development --chown=root:root /srv/client/.env /srv/backend # COPY . . -# CMD ["npm", "start"] \ No newline at end of file +# CMD ["node", "index.js"] diff --git a/docker-compose.yml b/docker-compose.yml index b92207eb8..b12581169 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,9 +1,69 @@ - -version: '3' +version: "3.8" services: + backend: + build: + context: ./backend + target: development + command: yarn run dev + volumes: + - ./backend:/srv/backend + - backend_node_modules:/srv/backend/node_modules + expose: + - "4000" + - "27017" + ports: + - "4000:4000" + - "27017:27017" + restart: on-failure + networks: + - gateway + + client: + build: + context: ./client + target: development + command: yarn run start + volumes: + - ./client:/srv/client + - client_node_modules:/srv/client/node_modules + expose: + - "3000" + - "4000" + ports: + - "3000:3000" + stdin_open: true + restart: on-failure + networks: + - gateway + + nginx: + restart: always + build: + dockerfile: Dockerfile.nginx + context: ./nginx + ports: + - "5000:80" + networks: + - gateway + depends_on: + - client + - backend + mailhog: - image: mailhog/mailhog - ports: + image: mailhog/mailhog + ports: - 1025:1025 # smtp server - 8025:8025 # web ui + depends_on: + - client + - backend + networks: + - gateway + +networks: + gateway: {} + +volumes: + client_node_modules: + backend_node_modules: diff --git a/nginx/.dockerignore b/nginx/.dockerignore new file mode 100644 index 000000000..7541db332 --- /dev/null +++ b/nginx/.dockerignore @@ -0,0 +1,6 @@ +.git +.dockerignore +docker-compose*.yml +npm-debug.log* +Dockerfile.* +node_modules diff --git a/nginx/Dockerfile.nginx b/nginx/Dockerfile.nginx new file mode 100644 index 000000000..de139f4ef --- /dev/null +++ b/nginx/Dockerfile.nginx @@ -0,0 +1,2 @@ +FROM nginx +COPY ./default.conf /etc/nginx/conf.d/default.conf diff --git a/nginx/default.conf b/nginx/default.conf new file mode 100644 index 000000000..874c4b489 --- /dev/null +++ b/nginx/default.conf @@ -0,0 +1,27 @@ +upstream client { + server client:3000; +} + +upstream backend { + server backend:4000; +} + +server { + listen 80; + + location /api { + proxy_pass http://backend; + } + + location / { + proxy_pass http://client; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Host $server_name; + } +} diff --git a/utils/local_db_backup.sh b/utils/local_db_backup.sh new file mode 100755 index 000000000..702be3163 --- /dev/null +++ b/utils/local_db_backup.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +<<'###BLOCK-COMMENT' +Backs up and restores MongoDB instance. + +Arguments: + -u URI of the source MongoDB instance + -d Database name of the source MongoDB instance + -h Host of MongoDB instance to restore backup + -p Port of MongoDB instance to restore backup + -n Name of new MongoDB database + +Example: + sh local_db_backup.sh -u YOUR_MONGO_DB_URL_SANS_ARGS -d SOURCE_DB_NAME -h localhost -p 27017 -n DESTINATION_DB_NAME + +###BLOCK-COMMENT + +while getopts u:d:h:p:n: flag + +do + case "${flag}" in + u) mongo_src_uri=${OPTARG};; + d) mongo_src_db_name=${OPTARG};; + h) mongo_dest_host=${OPTARG};; + p) mongo_dest_port=${OPTARG};; + n) mongo_dest_name=${OPTARG};; + esac +done + +if pgrep mongo > /dev/null +then + echo "MongoDB is already Running" +else + echo "Starting mongod daemon" + mongod +fi + +echo "Backing up mongodb from uri=$mongo_src_uri" +mkdir backup +mongodump --uri=$mongo_src_uri --out=backup + +echo "Restoring mongodb to host=$mongo_dest_host and port=$mongo_dest_port with name=$mongo_dest_name" +# need to remove hard coded value for incoming db_name "vrms_test" +mongorestore --host $mongo_dest_host --port $mongo_dest_port --db $mongo_dest_name ./backup/$mongo_src_db_name + +echo "Cleaning up" +rm -rf backup \ No newline at end of file