- Introduction
- Database Design
- API Endpoints
- Run this project
- Test Api's
OnePTE is a REST API built with Node.js and Express.js framework. It uses Sequelize as ORM to interact with MySQL database. The API is designed to manage questions and answers for a language proficiency test.
-
POST
/api/v1/users/registerRequest Body Example (Click here)
{ "name": "Yousuf Islam", "email": "[email protected]", "password": "12345@qQ" }Response example
{ "status": 201, "success": true, "message": "User created successfully", "data": null }
-
GET
/api/v1/users/history?type=SST&page=1&pageSize=5Query Parameters
Parameter Type Description typeenum (optional) Filters history by question type. Possible values: SST,RO,RMMCQ.pagestring (optional) Specifies the page number for pagination. Default is 1.pageSizestring (optional) Specifies the number of items per page. Default is 10.Request Headers
Header Name Value Type Description Cookiestring Contains accessTokenandrefreshTokenfor authentication.Request Example
GET /api/v1/users/history?type=SST&page=1&pageSize=5 HTTP/1.1 Host: your-api.com Cookie: accessToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsImlhdCI6MTY5MjQwNjAyMCwiZXhwIjoxNzI0MDY5MzIwfQ.wBq6BImUXNUp5SW8ptjY8q_W6oBzzNybjFdEKcICG_A; refreshToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsImlhdCI6MTcyNDA2OTAyMCwiZXhwIjoxNzI0NjczODIwfQ.XbP2M2SCo60_cCszqJKwd_zyoPH7b45aK2LQfY6ikZI
Response Example
{ "status": 200, "success": true, "message": "User history retrieved successfully", "data": { "totalItems": 2, "totalPages": 1, "currentPage": 1, "user": { "name": "Yousuf Islam" }, "history": [ { "answer": { "id": 1, "answer": [0, 1, 2], "score": 0, "max_score": 3 }, "question": { "id": 6, "type": "RMMCQ", "title": "RMMCQ Two", "sst": null, "ro": null, "rmmcq": { "id": 2, "options": [ "Not for one moment did he doubt the validity...", "This research seems to give some validity...", "I had no reason to question the validity...", "State officials questioned the validity of the report...", "The clause has no legal validity..." ] } } }, { "answer": { "id": 2, "answer": [0, 1, 2, 3], "score": 3, "max_score": 3 }, "question": { "id": 5, "type": "RO", "title": "RO Two", "sst": null, "ro": { "id": 2, "paragraphs": [ "Not for one moment did he doubt the validity...", "This research seems to give some validity...", "I had no reason to question the validity...", "State officials questioned the validity of the report..." ] }, "rmmcq": null } }, ] } }
-
POST
/api/v1/auth/loginRequest Body Example
{ "email": "[email protected]", "password": "12345@qQ" }Response Example
{ "status": 200, "success": true, "message": "Successfully logged in", "data": { "id": 1 } }
-
POST
/api/v1/auth/logoutRequest Headers
Header Name Value Type Description Cookiestring Contains accessTokenandrefreshTokenfor authentication.Response Example
{ "status": 200, "success": true, "message": "Successfully logged out", "data": null }
-
POST
/api/v1/auth/refresh-tokenRequest Headers
Header Name Value Type Description Cookiestring Contains accessTokenandrefreshTokenfor authentication.Response Example
{ "status": 200, "success": true, "message": "New access token generated successfully", "data": null }
-
POST
/api/v1/questionsRequest Headers
Header Name Type Description Cookiestring Contains accessTokenandrefreshTokenfor authentication.Content-Typestring Must be multipart/form-dataForm-Data Parameters
Parameter Name Type Description audio_filesfile Required for SST. Audio files (multiple files allowed).jsonDatatext Required. JSON string containing the question details.Example for
jsonData(as text):{ "type": "SST", "title": "Title must be a string", "time_limit": 20, "speakers": ["Speaker 1", "Speaker 2"], "paragraphs": ["paragraphs 1", "paragraphs 2", "paragraphs 3", "paragraphs 4"], "passage": "Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME 'users' AND TABLE_SCHEMA = 'onepte'", "options": ["options 1", "options 2", "options 3", "options 4", "options 5"], "correct_options": [1, 2, 4] }Response Example for SST Type Question
{ "status": 201, "success": true, "message": "Question created successfully", "data": { "question": { "id": 4, "type": "SST", "title": "Title must be a string", "sst_id": 1, "updatedAt": "2024-08-20T22:27:17.826Z", "createdAt": "2024-08-20T22:27:17.826Z" }, "details": { "id": 1, "time_limit": 20, "audio_files": [ { "fileUrl": "uploads/audio/1724192835930-AvoidRafa_(cover).mp3", "speaker": "Speaker 1" }, { "fileUrl": "uploads/audio/1724192836022-Music_(_no_copyright_Music_)_01.mp3", "speaker": "Speaker 2" } ], "updatedAt": "2024-08-20T22:27:16.084Z", "createdAt": "2024-08-20T22:27:16.084Z" } } }Response Example for RO Type Question
{ "status": 201, "success": true, "message": "Question created successfully", "data": { "question": { "id": 3, "type": "RO", "title": "Title must be a string", "ro_id": 1, "updatedAt": "2024-08-20T22:26:43.350Z", "createdAt": "2024-08-20T22:26:43.350Z" }, "details": { "id": 1, "paragraphs": [ "paragraphs 1", "paragraphs 2", "paragraphs 3", "paragraphs 4" ], "updatedAt": "2024-08-20T22:26:43.231Z", "createdAt": "2024-08-20T22:26:43.231Z" } } }Response Example for RMMCQ Type Question
{ "status": 201, "success": true, "message": "Question created successfully", "data": { "question": { "id": 2, "type": "RMMCQ", "title": "Title must be a string", "rmmcq_id": 2, "updatedAt": "2024-08-20T22:25:24.736Z", "createdAt": "2024-08-20T22:25:24.736Z" }, "details": { "id": 2, "passage": "Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME 'users' AND TABLE_SCHEMA = 'onepte'", "options": [ "options 1", "options 2", "options 3", "options 4", "options 5" ], "correct_options": [ 1, 2, 4 ], "updatedAt": "2024-08-20T22:25:24.472Z", "createdAt": "2024-08-20T22:25:24.472Z" } } }
-
GET
/api/v1/questions?page=1&pageSize=5Query Parameters
Parameter Type Description typeenum (optional) Filters questions by question type. Possible values: SST,RO,RMMCQ.pagestring (optional) Specifies the page number for pagination. Default is 1.pageSizestring (optional) Specifies the number of items per page. Default is 10.Request Headers
Header Name Value Type Description Cookiestring Contains accessTokenandrefreshTokenfor authentication.Response Example
{ "status": 200, "success": true, "message": "Questions fetched successfully", "data": { "totalItems": 41, "totalPages": 5, "currentPage": 1, "data": [ { "id": 1, "type": "SST", "title": "SST One", "sst_id": 1, "ro_id": null, "rmmcq_id": null, "createdAt": "2024-08-15T22:23:46.000Z", "updatedAt": "2024-08-15T22:23:46.000Z" }, { "id": 2, "type": "RO", "title": "RO One", "sst_id": null, "ro_id": 1, "rmmcq_id": null, "createdAt": "2024-08-15T22:24:44.000Z", "updatedAt": "2024-08-15T22:24:44.000Z" }, { "id": 3, "type": "RMMCQ", "title": "RMMCQ One", "sst_id": null, "ro_id": null, "rmmcq_id": 1, "createdAt": "2024-08-15T22:25:00.000Z", "updatedAt": "2024-08-15T22:25:00.000Z" }, { "id": 4, "type": "SST", "title": "SST Two", "sst_id": 2, "ro_id": null, "rmmcq_id": null, "createdAt": "2024-08-15T22:25:17.000Z", "updatedAt": "2024-08-15T22:25:17.000Z" }, { "id": 5, "type": "RO", "title": "RO Two", "sst_id": null, "ro_id": 2, "rmmcq_id": null, "createdAt": "2024-08-15T22:25:26.000Z", "updatedAt": "2024-08-15T22:25:26.000Z" }, { "id": 6, "type": "RMMCQ", "title": "RMMCQ Two", "sst_id": null, "ro_id": null, "rmmcq_id": 2, "createdAt": "2024-08-15T22:25:34.000Z", "updatedAt": "2024-08-15T22:25:34.000Z" }, { "id": 7, "type": "RMMCQ", "title": "Fix: Use Dynamic Assignment for questionData", "sst_id": null, "ro_id": null, "rmmcq_id": 3, "createdAt": "2024-08-17T22:59:26.000Z", "updatedAt": "2024-08-17T22:59:26.000Z" }, { "id": 8, "type": "SST", "title": "Fix: Use Dynamic Assignment for questionData", "sst_id": 3, "ro_id": null, "rmmcq_id": null, "createdAt": "2024-08-17T23:01:30.000Z", "updatedAt": "2024-08-17T23:01:30.000Z" }, { "id": 9, "type": "RO", "title": "Fix: Use Dynamic Assignment for questionData", "sst_id": null, "ro_id": 3, "rmmcq_id": null, "createdAt": "2024-08-17T23:01:38.000Z", "updatedAt": "2024-08-17T23:01:38.000Z" }, { "id": 10, "type": "RO", "title": "Fix: Use Dynamic Assignment for questionData", "sst_id": null, "ro_id": 4, "rmmcq_id": null, "createdAt": "2024-08-17T23:12:18.000Z", "updatedAt": "2024-08-17T23:12:18.000Z" } ] } }
-
GET
/api/v1/questions/:idQuery Parameters
Parameter Type Description idint Question ID Request Headers
Header Name Value Type Description Cookiestring Contains accessTokenandrefreshTokenfor authentication.Response Example
{ "status": 200, "success": true, "message": "Question fetched successfully", "data": { "id": 3, "type": "RO", "title": "Title must be a string", "details": { "id": 1, "paragraphs": [ { "index": 3, "value": "paragraphs 4" }, { "index": 2, "value": "paragraphs 3" }, { "index": 0, "value": "paragraphs 1" }, { "index": 1, "value": "paragraphs 2" } ] } } }
-
POST
/api/v1/answersRequest Headers
Header Name Value Type Description Cookiestring Contains accessTokenandrefreshTokenfor authentication.Request Body Example for RO & RMMQC Type
{ "questionId": 2, "answerData": [0, 1, 2, 3] }Note:TheanswerDatavalue is the array of numbers[0, 1, 2, 3]which is the index number of theRO's paragraphs &RMMCQ's options type question.Request Body Example for SST Type
{ "questionId": 2, "answerData": "Return Object from Scoring Functions: Each scoring function now returns an object with score and maxScore." }Reesponse Example
{ "status": 201, "success": true, "message": "Answer submitted successfully", "data": null }
To run the OnePTE API locally, follow these steps:
1. Clone the Repository:
First, clone the repository to your local machine using the following command:
git clone https://github.com/yousufislam191/OnePTE.git
cd OnePTE2. Install Dependencies:
Make sure you have Node.js and npm installed on your system. Then, install the required dependencies:
npm install3. Set Up Environment Variables:
Add the necessary environment variables in .env.development file as shown below:
SERVER_PORT = 3001
ALLOWED_ORIGINS = http://localhost:3000
NODE_ENV = development
API_PREFIX = /api/v1
APPLICATION_NAME = OnePTE
DB_HOST = localhost
DB_PORT = 3306
DB_LOGIN_NAME = root
DB_LOGIN_PASSWORD = root
DB_NAME = onepte
JWT_ACCESS_SECRET = myaccesssecret
JWT_ACCESS_EXPIRES_IN = 5m
JWT_REFRESH_SECRET = myrefreshsecret
JWT_REFRESH_EXPIRES_IN = 7dReplace DB_LOGIN_NAME, DB_LOGIN_PASSWORD, and onepte with your MySQL credentials and database name.
4. Set Up the Database:
Ensure MySQL is running on your machine. Then, run the following command to create and migrate the database:
npm run db:migrateThis will automatically create the database and apply any migrations.
5. Start the Application:
Start the server using the following command:
npm run devThe server should now be running at http://localhost:3001.
To run this project using Docker, follow these steps:
-
Install Docker Desktop and Git
-
Open a terminal and Clone this github repository
git clone https://github.com/yousufislam191/OnePTE.git
-
Enter the cloned repository
cd OnePTE -
Build and Start Containers:
Use the provided
docker-up.shscript to build the Docker images and start the containers. Run the following command:./docker-up.sh
This will execute the
docker-compose.ymlfile, build the necessary Docker images, and start the containers in detached mode. -
Stop and Remove Containers:
If you need to stop and remove the running containers, use the
docker-down.shscript. Run the following command:./docker-down.sh
This will execute the
docker-compose.ymlfile, stop and remove the running containers. -
Access the Application:
Once the containers are up and running,
- you can access the application at http://localhost:3001 in your browser or Postman.
- you can acces the database at http://localhost:8081 in your browser through
phpMyAdminwith theusername:rootandpassword:root.
To test api endpoint, download the Postman Collection file then import it into you postman.
