Simple Questios & Answers API with permissions.
There are 2 User Roles: ORGANIZER
and PARTICIPANT
. Only Organizers can create questions while both roles can answer questions.
Technologies
- Nest.js
- Prisma (With PostgresSQL)
- Docker
Technical Decisions
- Only Organizers can create Questions;
- Both roles can answer questions, but only once;
- Organizers cannot answer their own questions;
- There is no Administrator role, so anyone can create new Users. But User can only
π΅ GET
/π£ PATCH
/π΄ DELETE
their own information; - There is no route to get All users;
- Users can only
π£ PATCH
/π΄ DELETE
their own Questions/Answers; - A
PARTICIPANT
user can get only their own answers.ORGANIZER
users can get all answers from all questions.
1 - Clone the repository
git clone https://github.com/eduraio/qanda-api.git
2 - Install Dependecies
yarn install
3 - Populate .env file based on .env.example
DATABASE_URL="postgresql://user:password@localhost:5432/database?schema=public"
JWT_SECRET=
Note
Postgres User, Password and Database available on docker-compose.yml
Tip
Generate a JWT Secret, you can run the following script to generate yours:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
4 - Run docker-compose
docker-compose up
5 - Run Prisma Migrations
yarn prisma migrate dev
To start the project use:
yarn start
To run tests use:
yarn test
Tip
This project supports Swagger.
Access the API Documentation on http://localhost:3000/docs
Note that all routes, except π’ POST
/login and π’ POST
/users, are protected.
AccessTokens are valid for 10 minutes
You will need the AccessToken
to authenticate on other routes
Here goes all the routes. You can also check Docs for full details.
π
All routes, except π’ POST
/login and π’ POST
/users, must have an Authorization
header containing the accessToken
{
"Authorization": "Bearer {accessToken}"
}
π’ POST
/auth/login
Log In
Request Body
{
"email": "string",
"password": "string"
}
Response Application/json
{
"accessToken": "string"
}
Parameter | Description |
---|---|
id |
User UUID |
email UNIQUE |
User e-mail |
name |
User name |
password |
User password |
role |
Role of the user. ORGANIZER | PARTICIPANT |
questions? |
Array of questions created by this user |
answers? |
Array of answers created by this user |
created_at |
Date of creation |
updated_at |
Last updated date |
π’ POST
/users
Create a new user
Request Body
{
"email": "string",
"name": "string",
"password": "string",
"role": "ORGANIZER | PARTICIPANT"
}
Response Application/json
{
"id": "string",
"email": "string",
"name": "string",
"role": "ORGANIZER | PARTICIPANT",
"questions": [],
"answers": [],
"created_at": "date",
"updated_at": "date"
}
π΅ GET
/users/{id}
Get user info. User can get only their own information.
Request Body
{}
Response Application/json
{
"id": "string",
"email": "string",
"name": "string",
"role": "ORGANIZER | PARTICIPANT",
"questions": [],
"answers": [],
"created_at": "date",
"updated_at": "date"
}
π£ PATCH
/users/{id}
Update user info. User can update only their own information.
Request Body
{
"email": "string",
"password": "string",
"name": "string",
"role": "ORGANIZER | PARTICIPANT"
}
Response Application/json
{
"id": "string",
"email": "string",
"name": "string",
"role": "ORGANIZER | PARTICIPANT",
"created_at": "date",
"updated_at": "date"
}
π΄ DELETE
/users/{id}
Delete user info. User can delete only their own information.
Request Body
{}
Response Application/json
{
"id": "string",
"email": "string",
"name": "string",
"role": "ORGANIZER | PARTICIPANT",
"created_at": "date",
"updated_at": "date"
}
Parameter | Description |
---|---|
id |
User UUID |
question |
Question |
created_by_user_id |
Organizer user UUID |
answers? |
Array of answers for this question |
created_at |
Date of creation |
updated_at |
Last updated date |
Note
Property created_by_user_id
automatically populated based on logged in user
π’ POST
/questions
Create a new question. Only users with the role ORGANIZER
can create new questions.
Request Body
{
"question": "string"
}
Response Application/json
{
"id": "string",
"question": "string",
"created_by_user_id": "string",
"created_at": "date",
"updated_at": "date"
}
π΅ GET
/questions
Get all questions. This route returns the parameter answered_by_me
that indicates whether this questions was already answered by the user or not.
Paginated
Available Request Parameters
"order": "-- | ASC | DESC",
"limit": number,
"offset": number,
"sort": "-- | created_at",
"id": "Question UUID",
"question": "string",
"created_by_user_id": "User UUID"
Response Application/json
{
"results": [
{
"id": "string",
"question": "string",
"created_by_user_id": "string",
"created_at": "date",
"updated_at": "date",
"answered_by_me": true
}
],
"total": 0,
"limit": 25,
"offset": 0
}
π΅ GET
/questions/{id}/answers
Get all answers from the specified question. Only users with the role ORGANIZER
can have this information,
Paginated
Available Request Parameters
"order": "-- | ASC | DESC",
"limit": number,
"offset": number,
"sort": "-- | created_at",
"answer": "string",
"answer_by_user_id": "User UUID"
Response Application/json
{
"results": [
{
"id": "string",
"answer": "string",
"answer_by_user_id": "string",
"question_id": "string",
"created_at": "date",
"updated_at": "date"
}
],
"total": 0,
"limit": 25,
"offset": 0
}
π΅ GET
/questions/{id}
Get question information.
Request Body
{}
Response Application/json
{
"id": "string",
"question": "string",
"created_by_user_id": "string",
"created_at": "date",
"updated_at": "date",
"answered_by_me": true
}
π£ PATCH
/questions/{id}
Update a question. Only the question owner can update the question.
Request Body
{
"question": "string"
}
Response Application/json
{
"id": "string",
"question": "string",
"created_by_user_id": "string",
"created_at": "date",
"updated_at": "date"
}
π΄ DELETE
/questions/{id}
Delete a question. Only the question owner can delete the question.
Request Body
{}
Response Application/json
{
"id": "string",
"question": "string",
"created_by_user_id": "string",
"created_at": "date",
"updated_at": "date"
}
Parameter | Description |
---|---|
id |
User UUID |
answer |
Answer |
answer_by_user_id |
User UUID |
question_id |
Question UUID |
created_at |
Date of creation |
updated_at |
Last updated date |
Note
Property answer_by_user_id
automatically populated based on logged in user
π’ POST
/answers
Create a new answer to a question.
Request Body
{
"answer": "string",
"question_id": "string"
}
Response Application/json
{
"id": "string",
"answer": "string",
"answer_by_user_id": "string",
"question_id": "string",
"created_at": "date",
"updated_at": "date"
}
π΅ GET
/answers
Get all answers.
Users with the role PARTICIPANT
can get only their own answers.
Users with the role ORGANIZER
can get all answers.
Paginated
Available Request Parameters
"order": "-- | ASC | DESC",
"limit": number,
"offset": number,
"sort": "-- | created_at",
"answer": "string",
"answer_by_user_id": "User UUID",
"id": "Answer UUID",
Response Application/json
{
"results": [
{
"id": "string",
"answer": "string",
"answer_by_user_id": "string",
"question_id": "string",
"created_at": "date",
"updated_at": "date"
}
],
"total": 0,
"limit": 25,
"offset": 0
}
π΅ GET
/answers/{id}
Get answer information.
Users with the role PARTICIPANT
can get information only of their own answers.
Users with the role ORGANIZER
can get information from all answers.
Request Body
{}
Response Application/json
{
"id": "string",
"answer": "string",
"answer_by_user_id": "string",
"question_id": "string",
"created_at": "date",
"updated_at": "date"
}
π£ PATCH
/answers/{id}
Update a answer. Only the answer owner can update the answer.
Request Body
{
"answer": "string",
"question_id": "string"
}
Response Application/json
{
"id": "string",
"answer": "string",
"answer_by_user_id": "string",
"question_id": "string",
"created_at": "date",
"updated_at": "date"
}
π΄ DELETE
/answers/{id}
Delete a answer. Only the answer owner can delete the answer.
Request Body
{}
Response Application/json
{
"id": "string",
"answer": "string",
"answer_by_user_id": "string",
"question_id": "string",
"created_at": "date",
"updated_at": "date"
}