Web server providing endpoints for the UPchieve web client
Table of Contents
- Local Development
- Structure
- Endpoints
- POST /auth/login
- GET /auth/logout
- POST /auth/register/checkcred
- POST /auth/register
- POST /auth/reset/send
- POST /auth/reset/confirm
- POST /auth/reset/verify
- GET /auth/partner/volunteer
- GET /auth/partner/student
- GET /auth/partner/student/code
- POST /api/session/new
- POST /api/session/check
- POST /api/session/latest
- POST /api/training/questions
- POST /api/training/score
- POST /api/calendar/save
- POST /api/feedback
- GET /api/user
- PUT /api/user
- GET /api/user/:id
- POST /api/volunteers
- POST /api/volunteers/availability
- POST /api/verify/send
- POST /api/verify/confirm
- POST /moderate/message
- POST /eligibility/check
- GET /eligibility/school/search
- GET /eligibility/school/studentusers/:schoolUpchieveId
- Worker
Docker provides an alternative for local development. A docker-compose file exists, tied to Mongo. Here's how to work in docker-compose.
- Navigate to this directory and run
mkdir mongo-volume
to create a directory for the MongoDB volume. - Run
cp config.example.ts config.ts
to copy the default config as your own config. - Run
docker-compose up
to launch the server. - After any change: Run
docker-compose down --rmi all
to destry images and containers. Then rundocker-compose up
to see your changes.
Note: the default command ran when starting the server will populate/refresh all seed data, so any data changes to seed data will be overwritten.
If not using docker-compose, follow these steps to start required components.
The recommended tool for runtime version managment is asdf
and Docker
. To use asdf
on Windows, first install the appropriate Linux shell distribution using WSL
(Windows Subsystem for Linux).
You must use Node.js version 11.7.0
. Install the following asdf plugin:
-
nodejs version
11.7.0
asdf plugin-add nodejs https://github.com/asdf-vm/asdf-nodejs.git
bash ~/.asdf/plugins/nodejs/bin/import-release-team-keyring
asdf install nodejs 11.7.0
asdf global nodejs 11.7.0
node -v
The output of node -v
should be: v11.7.0
Using a Volume (else data is not saved), pull and run docker image mongo:4.2.3-bionic
. You can use any empty directory to which you have write access for your volume.
docker run -i --rm --name mongoContainer -p 27017-27019:27017-27019 -v <Absolute Path to directory on your drive>:/data/db mongo:4.2.3-bionic
Pull and run docker image redis:5.0.8
. You can use any empty directory to which you have write access for your volume.
docker run -i --rm --name redis -p 6379:6379 -v <Absolute Path to directory on your drive>:/data -t redis:5.0.8
- Try connecting to your database container by running
mongo
(see Mongo dependancy if this will not connect). Runquit()
to exit the shell. You can also interface with the database using a free MongoDB GUI such as MongoDB Compass Community - Run
cp config.example.ts config.ts
to copy the default config as your own config. - Run
npm install
to install the required dependancies. - Run
npx ts-node init
to seed the database with users, quiz questions, schools, and zip codes. - If you want to test Twilio voice calling functionality, set the
host
property to[your public IP address]:3000
(minus the brackets), and configure your router/firewall to allow connections to port 3000 from the Internet. Twilio will need to connect to your system to obtain TwiML instructions. - Run
npm run dev
to start the dev server onhttp://localhost:3000
. If you get abcrypt
compilement error, runnpm rebuild
. - See the web client repo for client installation.
- (optional) Run
redis-server
andnpm run worker:dev
to start the redis database and dev worker. The dev worker will automatically attempt to connect to your local Redis instance and read jobs from there. Additionally, you can runts-node ./scripts/add-cron-jobs.ts
to add all repeatable jobs to the job queue.
The database is populated with the following users for local development:
password | |
---|---|
[email protected] |
Password123 |
[email protected] |
Password123 |
[email protected] |
Password123 |
[email protected] |
Password123 |
By default, none of the test users have an approvedHighschool
set. The volunteers are all admins by default, and [email protected]
and [email protected]
have also passed all of their certifications. [email protected]
has not passed any quizzes.
The root folder of the repository provides the bootstrap file main.js
and a
package definitions file.
config.ts
contains a map of configuration keys for running the server. All
keys and sensitive information should be placed in this file.
Model definitions that map to database models, along with related methods to act on those models, such as parsing, validation, and data transformations.
Directory structure mimics the endpoint structure exposed by the server. Each file provides one or more endpoint routes, responsible for request acceptance/rejection and error handling.
Routes use controllers to perform the business logic of the server, providing separation of concerns: the controllers have no need to be aware of how the endpoints work. Instead, a controller provides ways to allow the routes to trigger something (a user update, e.g.)
A service is a step higher than a controller. Services provide abstract functions to one or many controllers, often to interface with third party services.
Expects the following request body:
{
"email": "String",
"password": "String"
}
Authenticates the user with a session if credentials are correct.
Removes the user's current session.
Check whether the credential user entered is valid. (first step of registeration) The server will check is there any duplications for email and validate the password.
{
"email": "String",
"password": "String"
}
Possible errors:
- Email/password not provided
- Password does not meet requirements
- Email is not valid
- Email already exists
Create a new account based on the information posted.
{
"email": "String",
"password": "String",
"code": "String",
"highSchool": "String",
"firstName": "String",
"lastName": "String"
}
Possible errors:
- Email/password not provided
- Password does not meet requirements
- Email is not valid
- Email already exists
- Could not hash password
- Could not send verification email (for volunteers)
{
"email": "String"
}
{
"email": "String",
"password": "String",
"newpassword": "String",
"token": "String"
}
{
"token": "String"
}
Expects the following query string:
?partnerId=PARTNER_ID
where PARTNER_ID
is the key name of the volunteer partner organization defined in config.ts
under volunteerPartnerManifests
.
Returns a volunteer partner manifest object.
Expects the following query string:
?partnerId=PARTNER_ID
where PARTNER_ID
is the key name of the student partner organization defined in config.ts
under studentPartnerManifests
.
Returns a student partner manifest object.
Expects the following query string:
?partnerSignupCode=PARTNER_SIGNUP_CODE
where PARTNER_SIGNUP_CODE
is equal to a signupCode
defined in config.ts
under studentPartnerManifests
.
Returns a student partner manifest key name.
{
"sessionType": "String",
"sessionSubTopic": "String"
}
{
"sessionId": "String"
}
{
"user_id": "String"
}
{
"category": "String"
}
{
"idAnswerMap": "String",
"category": "String"
}
{
"availability": {
"Sunday": {
"12a": "Boolean",
"1a": "Boolean",
...
},
"Monday": {
...
},
...
},
"tz": "String"
}
{
"sessionId": "String",
"topic": "String",
"subTopic": "String",
"responseData": "String"
}
Returns a sanitized public user record for the currently authenticated user
Accepts a request body with fields mapping to profile fields to update for the currently authenticated user:
{
"phone": "String"
}
Returns a sanitized public user record for a user with the given id. May perform checks on the authorization level of the current user to strip out priveliged information.
Returns an object with all the users who are volunteers. All the keys are user ids.
Returns a map with the availability of all the volunteers. All the keys are user ids.
Sends an email to verify the current user with unique hash. The email provided will overwrite the user record's email, in the event that the two do not match.
{
"email": "String"
}
Accepts a token used to verify the current user.
{
"token": "String"
}
Expects the following request body:
{
"content": "string with the content of a message"
}
Returns a boolean indicating whether or not the message is clean.
The response body looks like this if no error occurred:
{
"isClean": true // or false
}
Expects the following request body:
{
"schoolUpchieveId": "String",
"zipCode": "String",
"email": "String"
}
Expects the following query string:
?q=SEARCH_STRING
where SEARCH_STRING
is the string to be searched.
Searches the database of schools for a name or upchieveId
matching the search string. The search string may match only part of the school's name, but if searching for an upchieveId
the string must match exactly.
If there are no errors, the response body contains the list of schools matching the search string in the format:
{
"results": [
{
"upchieveId": "UPchieve ID",
"name": "high school name",
"districtName": "district name",
"city": "city name",
"state": "state postal code"
},
// ...
]
}
Adds an email address to the list of email addresses to notify when the school is approved by UPchieve.
If no error occurred, the response body looks like:
{
"schoolId": "School's UPchieve ID"
}
Checks if a student is eligible for UPchieve based on their school and zip code. If no error occurs, the response looks like:
{
"isEligible": true // or false
}
Lists all student users registered with a school. Restricted to admins only. If no error occurs, the response looks like:
{
"upchieveId": "8-digit identifier",
"studentUsers": [
{
"email": "[email protected]",
"firstname": "Firstname",
"lastname": "Lastname",
"userId": "user's ObjectID in MongoDB"
},
// ...
]
}
A Bull worker reading from a local Redis database. Job definitions live in worker/jobs
and are registered in worker/jobs/index.ts
. A script scripts/add-cron-jobs.ts
will insert all repeatable jobs into the local Redis database.
- Update Elapsed Availability: updates all volunteers' elapsed availabilities every day at 4 am.