-
Notifications
You must be signed in to change notification settings - Fork 0
Node.js Server
The API for this project allows an examiner to login to the evaluation mobile app, view team average scores and evaluate and reevaluate teams for their poster based on a set of questions. It also allows an admin to view all teams, their average scores, score board of every individual team, create new examiners and teams and provide information for generating a QR code for each team and examiner. The API uses MongoDB Atlas cloud database and Digital Ocean Ubuntu droplet for hosting our API.
The end points are as follows:
- GET: 64.227.27.167:3000/api/v1/users/login
- POST: localhost:3000/api/v1/admin/examiners
- POST: 64.227.27.167:3000/api/v1/admin/teams
- GET: 64.227.27.167:3000/api/v1/admin/examiners
- GET: 64.227.27.167:3000/api/v1/admin/examiners/<examiner_id>
- GET: 64.227.27.167:3000/api/v1/admin/teams
- GET: 64.227.27.167:3000/api/v1/admin/teams/<team_id>
- GET: 64.227.27.167:3000/api/v1/admin/examiners/<examiner_id>/qrToken
- GET: 64.227.27.167:3000/api/v1/admin/teams/<team_id>/qrToken
- GET: 64.227.27.167:3000/api/v1/examiner/teams
- GET: 64.227.27.167:3000/api/v1/examiner/questions
- GET: 64.227.27.167:3000/api/v1/examiner/questions/<question_id>
- POST: 64.227.27.167:3000/api/v1/examiner/score
- GET: 64.227.27.167:3000/api/v1/users/profile
Before any or some of this functionality is provided, this API will execute some custom middleware as discussed below:
1. Connecting to Database:
Before hitting any of the above listed endpoints, our API needs to connect to our MongoDB Atlas database to retrieve/save/update data. This middleware will establish this connection with the database using a database URL before processing any request. If the connection is established, the request will forward to the intended endpoint or the next middleware (as suited for the specific case), otherwise an error response will be returned to the users specifying that the database connection cannot be established.
2. Authenticating user:
This middleware will execute only for users who are logged into the system using the login functionality. Whenever a user tries to access any of the above mentioned endpoints, a JWT bearer token needs to be specified in the Authorization header in the request along with other endpoint specific data. This middleware will check for this token. If the token is not found in the request or has elapsed the duration of 1 hour/24 hours (token time to live depends upon mechanism used for login) since its issuance then an error response will be sent to the users with an appropriate response, otherwise on successful validation of the token, the API will then proceed to fulfill the request using the appropriate endpoint or go on to the next middleware as suited for the specific case. The JWT is created and validated in the API using jsonwebtoken library of node. Every token issued after username and password login has 60 minutes time to live and every token returned after login done using pre-issued bearer token has 24 hours time to live, after which the token will be treated as invalid.
3. Authorizing examiner: This middleware will execute only for endpoints beginning with '/api/v1/examiner' pattern. It will make sure that users trying to use the endpoints with the mentioned pattern as essentially examiners by role. The token decoded while authenticating the user will be checked for its role parameter in this middleware. If a role is not found or if found is anything else than examiner, then an error response is sent back to the user. If the decoded token value has role as examiner, it will go on to fulfill the user request by hitting the intended endpoint.
3. Authorizing admin: This middleware will execute only for endpoints beginning with '/api/v1/admin' pattern. It will make sure that users trying to use the endpoints with the mentioned pattern as essentially admins by role. The token decoded while authenticating the user will be checked for its role parameter in this middleware. If a role is not found or if found is anything else than admin, then an error response is sent back to the user. If the decoded token value has role as admin, it will go on to fulfill the user request by hitting the intended endpoint.
Let's now discuss the API end points in details:
1. GET: 64.227.27.167:3000/api/v1/users/login
Header:
1. {Authorization:Basic <base64encoded_email:password>}
2. {Authorization:Basic Bearer <token>}
This endpoint allows an admin to login using email and password and allows an examiner to login using email and password or a pre-issued bearer token. If the authorization header type is encountered to be 'Basic', then the end point checks if the user with the given email id exists in the system or not and if they do, is the correct password provided for the user. If the user has provided proper and existant login credentials, then the user is returned in the response along with a jwt token having a ttl of one hour. Otherwise, an error response will be returned. In order to check if the incoming password matches the password present in the database for the specific user, this password is hashed and salted and compared to the hashed and salted password present in the database. This is done using bcrypt.js. This login method can be used for login by both examiner and admin. The second login method that can be used is by providing a pre-issued bearer token in the Authorization header (token generated by endpoint 8). This login mechanism can be used only by examiners. Hence on encountering a bearer authorization header, the endpoint will first decode the token. If the token is valid the role on the decoded token will be checked. If a role is present on the decoded token and it has value examiner, then the profile info will be returned to the user. In all other cases, an error response will be returned back. This will ensure that only an examiner uses this method of authentication for login.
2. POST: localhost:3000/api/v1/admin/examiners
Header:
{Authorization:Basic Bearer <token>}
Body:
{
"firstName":"Michael",
"lastName":"Joe",
"email":"michael@gmail.com",
"password":"examiner123"
}
Examiners can only be created by a user having admin role. Upon making a post request to this endpoint, if all the provided data is correct and passes the set validations, the examiner will be created successfully by the endpoint and returned back to the user in the response (without the password). While saving the examiner password to the database, the password will be hashed and salted using bcrypt.js and then will be stored in the database for that specific examiner. In order to create a new examiner, they need to have a unique email id, otherwise the api will send an error response back to the user. Examiner will be created only if the first name and last name have only alphabetical values, the password has minimum 6 and maximum 20 character, the email id is unique and all parameters are provided.
3. POST: 64.227.27.167:3000/api/v1/admin/teams
Header:
{Authorization:Basic Bearer <token>}
Body:
{
"name":"game of thrones",
"members":"aditi,venu,gayatri,eesha"
}
Teams can only be created by a user having admin role. Upon making a post request to this endpoint, if all provided data is correct and passes the set validations, the team will be created successfully by the endpoint and returned back to the user in the response. In order create a new team, the team name should be unique, otherwise the api will send an error response back to the user. Team will be created if the team name is unique and is not a numeric value and has at least 1 and at most 4 members.
4. GET: 64.227.27.167:3000/api/v1/admin/examiners
Header:
{Authorization:Basic Bearer <token>}
This endpoint can only be used by a user having admin role. It will return a list of all examiners present in the system database. Here, examiners can be filtered by first name, last name and email as well. An error will be returned if no examiners are present.
5. GET: 64.227.27.167:3000/api/v1/admin/examiners/<examiner_id>
Header:
{Authorization:Basic Bearer <token>}
This endpoint can only be used by a user having admin role. It will return an examiner with the specified examiner_id (except password). If the examiner id is not of correct mongo id format or if a user with the given examiner_id is not present in the database, an error will be returned back to the user.
6. GET: 64.227.27.167:3000/api/v1/admin/teams
Header:
{Authorization:Basic Bearer <token>}
This endpoint can only be used by a user having admin role. It will return a list of all teams present in the system database. Here, teams can be filtered by team name. An error will be returned if no teams are present.
7. GET: 64.227.27.167:3000/api/v1/admin/teams/<team_id>
Header:
{Authorization:Basic Bearer <token>}
This endpoint can only be used by a user having admin role. It will return a team with the specified team_id. If the team id is not of correct mongo id format or if a team with the given team_id is not present in the database, an error will be returned back to the user.
8. GET: 64.227.27.167:3000/api/v1/admin/examiners/<examiner_id>/qrToken
Header:
{Authorization:Basic Bearer <token>}
This endpoint can only be used by a user having admin role. If the examiner with the specified examiner_id is present in the database, a jwt token is created using the examiner data, having a time to live of 24 hours and is returned back to the user in the response. This token can then be used by the examiner to login using bearer token authorization header (in login endpoint). If an examiner with the specified examiner_id is not found or the examiner_id is not of mongo id format, an appropriate error response is sent back to the user.
9. GET: 64.227.27.167:3000/api/v1/admin/teams/<team_id>/qrToken
Header:
{Authorization:Basic Bearer <token>}
This endpoint can only be used by a user having admin role. If the team with the specified team_id is present in the database, a jwt token is created using the team data, having a time to live of 24 hours and is returned back to the user in the response. This token can then be used by the examiner to uniquely identify a team using endpoint listed at number 10. If a team with the specified team_id is not found or the team_id is not of mongo id format, an appropriate error response is sent back to the user.
10. GET: 64.227.27.167:3000/api/v1/examiner/teams
Header:
{
Authorization:Basic Bearer <token>,
teamToken: <team_token>
}
This endpoint can only be used by a user having examiner role. It allows the examiner to fetch team name, members and average score of all teams present in the database. The header teamToken is optional, but if provided it needs to be a valid jwt token. If not, an error will be returned to the user. If the team token is given and is valid the team_id will be fetched from the decoded token value and the team name, members and average score of the team corresponding to the team_id recovered from the token will be returned to the examiner. The team token generated from endpoint listed at no. 9 can be used to specify the teamToken in the header. If a team corresponding to the team_id recovered from the decoded teamToken is not found, an error response is returned back to the user.
11. GET: 64.227.27.167:3000/api/v1/examiner/questions
Header:
{Authorization:Basic Bearer <token>}
This endpoint can only be used by a user having examiner role. It returns all questions stored on the server along with the id and the question itself to the examiner. These questions are the questions the examiner needs to answer in order to evaluate a team.
12. GET: 64.227.27.167:3000/api/v1/examiner/questions/<question_id>
Header:
{Authorization:Basic Bearer <token>}
This endpoint can only be used by a user having examiner role. It will return the the question with the mentioned question_id to the examiner. These questions are the questions the examiner needs to answer in order to evaluate a team. If the question_id is not of int format or no question with the given id is present on the server, the endpoint will return an appropriate error response.
13. POST: 64.227.27.167:3000/api/v1/examiner/score
Header:
{Authorization:Basic Bearer <token>}
Body:
{
"teamId":"5f8a5a39aa55543f8901cc85",
"scores":[
{"id":1,"marks":2},
{"id":2,"marks":0},
{"id":3,"marks":3},
{"id":4,"marks":2},
{"id":5,"marks":4},
{"id":6,"marks":4},
{"id":7,"marks":3}
]
}
This endpoint can only be used by a user having examiner role. It allows an examiner to evaluate/reevaluate a team by giving marks for each evaluation question for the poster of the team. In order to evaluate a team, first the teamId needs to be given, should be of mongo id format and a team corresponding to the given teamId should be present in the database. Also, in the scores array, every question (questions from id 1 to 7) needs to be assigned some marks. None of the questions should be missing or unmarked. No questions should be assigned marks twice or more. Every question can have lowest marks 0 and highest marks 4. Marks can be awarded only in the range of 0 to 4 and should all be integer values. The ids of questions also need to be integer values and the ids should correspond with a question on the server. If any of the mentioned conditions are violated, an appropriate error response is returned back to the examiner. If all the provided data is valid, the endpoint will check if this particular examiner evaluating this team has previously evaluated the same team or not. If the examiner is evaluating the team for the first time, the total of the marks will be calculated, the examiners complete evaluation (evaluation of each question and total of all questions) will be saved to the database. Along with storing the complete evaluation for the specific examiner, the new average score of the team is calculated by taking an average of the scores of all examiners who evaluated the team (including our new examiner) and the new average is stored/updated in the database for that particular team. If the examiner has already evaluated the team, the original evaluation on the database will be replaced by the new evaluation (individual question marks and score total) and the average team score will be updated based on the examiner's newly assigned score to the team.
14. GET: 64.227.27.167:3000/api/v1/users/profile
Header:
{Authorization:Basic Bearer <token>}
This endpoint can be used by examiners as well as admins. It returns the user info (except for password) from the token provided in the authorization header. If a user corresponding to the user id found in the decoded token is not found in the database, an appropriate error is returned back to the user.
We have used MongoDB database for our application. The database resides on an Atlas cloud cluster.
1. The database has a users collection which will store the following fields when a user is created.
- _id : This is the unique id generated by mongoDB automatically for the record entry.
- firstName : First name of user
- lastName : Last Name of user
- email : Email ID of user. This is a unique field, hence no two records can have the same email id (since it is used for user login)
- password : Hashed and salted value of user password.
- role : Role of the user in the system. This value can be either examiner or admin.
2. The database also has a teams collection which will store the following fields
- _id : This is the unique id generated by mongoDB automatically for the record entry.
- name : Name assigned to the team. This is a unique field, hence no two teams can have the same name.
- members : Array of all members of the team (array of string values)
- averageScore : Average score of team generated by calculating average of scores assigned to the team by all examiners who evaluated the team.
- examiners : Array all examiners who evaluated the team.
Each examiner object stores the following data in examiners array:
- examinerId : Unique ID on examiner who evaluated the team.
- examinerFirstName : First name of examiner who evaluated the team.
- examinerLastName : Last name of examiner who evaluated the team.
- score : Total score the examiner awarded to the team (total of marks assigned to each question).
- questions : Array of all questions and marks assigned for those questions to the team by the examiner.
Each question object store the following data in the questions array:
- id : Id of the question being evaluated.
- marks : Marks assigned to the particular question (0-4) by the examiner.
All information about the questions used to evaluate a team is present on the server. A json file holding the list of all questions is stored on the server. This json file data is itself used to return the questions to the examiners. Each question item in the json file stores the following information:
- id: Unique ID of the question
- question: The text of the question used for evaluation




