The API is meant to be used for an opinion poll application. Users can rate questions on a scale from 0 to 10. The server should store the ratings and calculate the average rating for each question.
Your task is to create a RESTful API server using Express.js. Briefly summarized, the server should:
- Authenticate users Iris and Max using bcrypt hashes stored in the users file.
- Serve questions and accept ratings based on predefined data in JSON files.
- Keep track of user ratings and calculate average scores.
- Set up a basic Express server that listens for incoming HTTP requests.
- Implement routes for the endpoints (listed below) with appropriate HTTP methods and responses.
- Create a login mechanism that checks user credentials against the
data/users.json
file. - Use JWT (JSON Web Tokens) to secure the endpoints.
- Use the predefined functions
read
andwrite
fromsrc/tools/json-files.js
to read and write data to/from the JSON files. - Calling
write('filename.json')
with a filename that does not exist will create a new file.
- Implement API endpoints to authenticate, retrieve questions, start polls, and provide ratings for a poll.
- Use JOI to validate user input, ensuring that submitted data follows the correct format.
- Use jest and supertest to write tests, proving your code works correctly.
- Accepts the username and password via "HTTP Basic" authentication scheme.
- On successful authentication, returns a JSON Web Token (JWT), which clients will use to access API endpoints subsequently.
- If authentication fails, returns a 401 Unauthorized status with a relevant message.
- Authorization: All users (authenticated or not) can access this endpoint.
- Retrieve the properties
id
andquestion
of all questions stored indata/questions.json
. - Authorization: All users (authenticated or not) can access this endpoint.
- Retrieve the properties
id
andquestion
for a specific question by its UUID. - If the
questionId
does not exist, respond with a 404 Not Found HTTP status code. - Authorization: All users (authenticated or not) can access this endpoint.
- Create a new poll and store it with the following schema:
{
"id": "3d13ee89-f02b-4783-bb0e-c2d441a62b4b", // UUID
"userName": "Iris", // The user's name
"createdAt": 1715003838, // Current timestamp
"responses": {} // Empty hash object for now
}
- Request body: empty (all data is generated by the server).
- Response body: the ID of the newly created poll (
pollId
). - Authorization: Only authenticated users can access this endpoint.
- Submit a rating to specific questions within a poll.
- Request body: JSON object containing the
questionId
and the submittedrating
(integer between 0 and 10). Example:
{ "544db309-40cf-4dd8-8662-c10ed3502a5d" : 7 }
- Updates the specified poll in the
polls.json
file. Example after above submission:
{
"id": "3d13ee89-f02b-4783-bb0e-c2d441a62b4b", // UUID of the poll
"userName": "Iris", // The user's name
"createdAt": 1715003838, // Timestamp
"responses": {
"544db309-40cf-4dd8-8662-c10ed3502a5d": 7 // <questionId>: <rating>
}
}
- Authorization: Authenticated users can POST to this endpoint only if the referenced poll is owned by them.
- Retrieve the average rating for a specific question, taking into account all submitted polls.
- If the
questionId
does not exist, respond with a 404 Not Found HTTP status code. - Authorization: All users (authenticated or not) can access this endpoint.
{
"average": 7.5 // The average rating for the question
}
- Use JOI to validate user input, ensuring that submitted ratings follow the correct format and are within the 0 to 10 range.
- Return meaningful error messages and HTTP status codes for invalid or unauthorized requests.
- Create API tests to ensure all API endpoints work correctly.
The questions are stored as an array in the file data/questions.json
and have the following data structure:
id
(uuid): Unique identifier for a questionquestion
(string): Actual question text
The users file (data/users.json
) contains two users:
- Name: Iris, Password: 123
- Name: Max, Password: 123
Use Iris and Max for authentication. The passwords are stored as cryptographic hashes, created with the bcrypt algorithm. When verifying the password, please pay attention to comparing hashes, not the plain password with the stored hash.