A single-page application for a team to track their progress in the Ultimate Functional Training Challenge, a fun exercise competition designed to promote an active lifestyle and get software engineers up from their desks during the work day.
Participants record their exercises and gain points, trying to reach a set goal. Upon gaining enough points on a single activity, or during a special one-day-challenge, participants are rewarded with badges.
This was a capstone project for a University of Turku Full Stack bootcamp, which took place between March and August of 2019. A team of five was given two months and free hands to design and build it. Original concept and support was provided by Ambientia.
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.
Make sure you have a recent version of Node.js installed.
This backend server should be started on the same host as the React frontend.
Clone the repository.
git clone https://github.com/simosavonen/uftc-backend.git
cd uftc-backend
Install Node.js modules.
npm install
Create a file '.env' at the root, in the same folder as index.js or app.js. Copy the following lines and edit the values to work with your setup.
Define the ports for express server, port 3000 is taken by the React frontend.
PORT=3001
TEST_PORT=3001
For password reset emails, the backend needs to know what the host URL is.
SITE_URL=http://localhost:3000
PROD_SITE_URL=https://yourdomain.com
We used MongoDB Atlas as our development and testing database. For deployment, MongoDB was installed on the Ubuntu server.
MONGODB_URI=mongodb+srv://username:password@server/uftc?retryWrites=true&w=majority
TEST_MONGODB_URI=mongodb+srv://username:password@server/uftctest?retryWrites=true&w=majority
PROD_MONGODB_URI=mongodb://username:password@localhost/uftc?retryWrites=true&w=majority
Define the secret phrase used to encrypt the JSON Web Tokens.
SECRET=youbetterchangethistoalongrandomtext
To create an account on the React frontend, users enter the site using a provided link containing this secret phrase.
SECRET_FOR_REGISTERING=keepthisurlsafe
Password reset emails are sent using Nodemailer and a gmail account. To get this to work, needed to loosen the security settings in gmail.
[email protected]
EMAIL_PASSWORD=password
Start the backend with nodemon, any changes to the files will restart the server.
npm run watch
We chose to deploy this on an AWS EC2 Ubuntu server. After gaining SSH access to it, install a webserver, Node.js and MongoDB.
sudo apt update
sudo apt upgrade
sudo apt install nginx npm nodejs mongodb
NGINX was used to serve the React frontend files, and the backend was started and kept running on host restarts by PM2.
Deploying the backend involved copying the files over to the user 'ubunbu' home folder, installing the Node.js modules and starting the Express server with PM2.
npm install
sudo npm install -g pm2
pm2 start npm -- start
Setting up NGINX and securing the MongoDB are beyond the scope of this readme.
- Express - Web Framework for Node.js
- Passport - Authentication for Node.js
- Nodemailer - Send emails from Node.js
- Mongoose - MongoDB object modeling for Node.js
- MongoDB - Database
- @shonkala - endpoint for achievements
- @MMattila75 - endpoint for resetting the DB for Cypress tests
- @simosavonen - the rest
- FullStackOpen - Helsinki University's free course material
- Ambientia - Original concept, support and guidance
- Jarko Papalitsas - Tutorial on deploying to AWS EC2
$ = protected by Passport.js, and requires an Authorization header with a valid JSON Web Token
- POST /api/users/register (checks for the secret phrase)
- POST /api/users/login
- $ PUT /api/users/:id (can only update your own info)
- $ GET /api/users/me
- $ GET /api/users/ (retuns a list of abbreviated names)
- GET /api/challenges
- $ POST /api/challenges (if the database was empty, you are set as the organizer)
- $ PUT /api/challenges/:id (limited to organizers)
- $ DELETE /api/challenges:id (organizers, cannot delete the last object)
- GET /api/activities
- $ POST /api/activities (organizers)
- $ PUT /api/activities (organizers)
- $ GET /api/workouts (returns your workouts)
- $ GET /api/workouts/:userid
- $ POST /api/workouts/:activityid
- $ PUT /api/workouts/:id (can only update your own workouts)
- $ DELETE /api/workouts/:id
- $ DELETE /api/workouts/:workout/:instance (deletes a date from instances array)
- GET /api/achievements
- GET /api/achievements/daily (one-day-challenges for today)
- GET /api/achievements/daily/:date
- GET /api/achievements/activity/:id
- $ POST /api/achievements (organizers)
- $ PUT /api/achievements/:id (organizers)
- $ DELETE /api/achievements/:id (organizers)
- GET /api/scores/weekly (returns a formatted result for use in Apex Chart diagram)
- GET /api/scores/byactivity
- POST /api/passwords (sends the reminder email)
- POST /api/passwords/verify (checks the token is still valid)
- POST /api/passwords/reset