PowerAPI is a RESTful service designed to manage power banks, their assignments to stations and warehouses, and user interactions. This API supports typical CRUD operations and includes custom endpoints for specific use cases like assigning power banks to stations, warehouses, or users.
- Ruby on Rails as the web backend framework this API's build with.
- PostgreSQL as the database for robust data management.
- JWT (JSON Web Tokens) for secure authentication and authorization.
- RSpec for comprehensive testing to ensure code quality and reliability.
To set up the project locally, follow these steps:
-
Clone the repository:
git clone https://github.com/MusaabAlfalahi/powerAPI.git cd powerAPI
-
Install dependencies:
Ensure you have Ruby and Bundler installed. Then run:
bundle install
-
Set up environment variables:
Create a
.env
file in the root directory of the project and add your environment variables, such as secret keys and database URLs. For example:DB_USERNAME= <your_db_username> DB_PASSWORD= <your_db_password>
-
Set up the database:
Ensure you have PostgreSQL installed and running. Configure your database settings in
config/database.yml
and then run:rails db:create rails db:migrate rails db:seed
To start the Rails server, run:
rails server
The API will be available at http://localhost:3000.
-
Login:
POST /login
- Request:
{ "email": "[email protected]", "password": "password" }
- Response:
{ "user": { "id": 1, "email": "[email protected]" }, "token": "jwt_token" }
- Request:
-
Logout:
DELETE /logout
- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
- Response:
204 No Content
- Request: Headers:
- Create User:
POST /users
admin only- Request:
{ "email": "[email protected]", "password": "password", "password_confirmation": "password" }
- Response:
{ "id": 1, "email": "[email protected]" }
- Request:
-
List Locations:
GET /locations
- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
- Response:
[ { "id": 1, "name": "Location 1", "address": "Address 1" }, ... ]
- Request: Headers:
-
Show Location:
GET /locations/:id
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
- Response:
{ "id": 1, "name": "Location 1", "address": "Address 1" }
- Request: Headers:
-
Create Location:
POST /locations
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Body:{ "name": "New Location", "address": "New Address" }
- Response:
{ "id": 1, "name": "New Location", "address": "New Address" }
- Request: Headers:
-
Update Location:
PUT /locations/:id
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Body:{ "name": "Updated Location", "address": "Updated Address" }
- Response:
{ "id": 1, "name": "Updated Location", "address": "Updated Address" }
- Request: Headers:
-
Delete Location:
DELETE /locations/:id
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
- Response:
204 No Content
- Request: Headers:
-
Search Locations:
GET /locations/search
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Params:{ "query": "search_term" }
- Response:
[ { "id": 1, "name": "Location 1", "address": "Address 1" }, ... ]
- Request: Headers:
-
List Stations:
GET /stations
- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
- Response:
[ { "id": 1, "name": "Station 1", "status": "active" }, ... ]
- Request: Headers:
-
Show Station:
GET /stations/:id
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
- Response:
{ "id": 1, "name": "Station 1", "status": "active" }
- Request: Headers:
-
Create Station:
POST /stations
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Body:{ "name": "New Station", "status": "active" }
- Response:
{ "id": 1, "name": "New Station", "status": "active" }
- Request: Headers:
-
Update Station:
PUT /stations/:id
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Body:{ "name": "Updated Station", "status": "inactive" }
- Response:
{ "id": 1, "name": "Updated Station", "status": "inactive" }
- Request: Headers:
-
Delete Station:
DELETE /stations/:id
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
- Response:
204 No Content
- Request: Headers:
-
Assign Station to Location:
PUT /stations/:id/location
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Body:{ "location_id": 1 }
- Response:
{ "id": 1, "name": "Station 1", "location_id": 1 }
- Request: Headers:
-
Assign Station to Warehouse:
PUT /stations/:id/warehouse
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Body:{ "warehouse_id": 1 }
- Response:
{ "id": 1, "name": "Station 1", "warehouse_id": 1 }
- Request: Headers:
-
Search Stations:
GET /stations/search
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Params:{ "query": "search_term" }
- Response:
[ { "id": 1, "name": "Station 1", "status": "active" }, ... ]
- Request: Headers:
-
List Warehouses:
GET /warehouses
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
- Response:
[ { "id": 1, "name": "Warehouse 1", "location_id": 1 }, ... ]
- Request: Headers:
-
Show Warehouse:
GET /warehouses/:id
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
- Response:
{ "id": 1, "name": "Warehouse 1", "location_id": 1 }
- Request: Headers:
-
Create Warehouse:
POST /warehouses
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Body:{ "name": "New Warehouse", "location_id": 1 }
- Response:
{ "id": 1, "name": "New Warehouse", "location_id": 1 }
- Request: Headers:
-
Update Warehouse:
PUT /warehouses/:id
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Body:{ "name": "Updated Warehouse", "location_id": 1 }
- Response:
{ "id": 1, "name": "Updated Warehouse", "location_id": 1 }
- Request: Headers:
-
Delete Warehouse:
DELETE /warehouses/:id
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
- Response:
204 No Content
- Request: Headers:
-
Search Warehouses:
GET /warehouses/search
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Params:{ "query": "search_term" }
- Response:
[ { "id": 1, "name": "Warehouse 1", "location_id": 1 }, ... ]
- Request: Headers:
-
List Power Banks:
GET /power_banks
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
- Response:
[ { "id": 1, "name": "Power Bank 1", "status": "available" }, ... ]
- Request: Headers:
-
List available Power Banks:
GET /power_banks/available
- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
- Response:
[ { "id": 1, "name": "Power Bank 1", "status": "available" }, ... ]
- Request: Headers:
-
Show Power Bank:
GET /power_banks/:id
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
- Response:
{ "id": 1, "name": "Power Bank 1", "status": "available" }
- Request: Headers:
-
Create Power Bank:
POST /power_banks
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Body:{ "name": "New Power Bank", "status": "available" }
- Response:
{ "id": 1, "name": "New Power Bank", "status": "available" }
- Request: Headers:
-
Update Power Bank:
PUT /power_banks/:id
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Body:{ "name": "Updated Power Bank", "status": "in_use" }
- Response:
{ "id": 1, "name": "Updated Power Bank", "status": "in_use" }
- Request: Headers:
-
Delete Power Bank:
DELETE /power_banks/:id
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
- Response:
204 No Content
- Request: Headers:
-
Assign Power Bank to Station:
PUT /power_banks/:id/station
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Body:{ "station_id": 1 }
- Response:
{ "id": 1, "name": "Power Bank 1", "station_id": 1 }
- Request: Headers:
-
Assign Power Bank to Warehouse:
PUT /power_banks/:id/warehouse
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Body:{ "warehouse_id": 1 }
- Response:
{ "id": 1, "name": "Power Bank 1", "warehouse_id": 1 }
- Request: Headers:
-
Assign Power Bank to User:
PUT /power_banks/:id/user
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Body:{ "user_id": 1 }
- Response:
{ "id": 1, "name": "Power Bank 1", "user_id": 1 }
- Request: Headers:
-
Search Power Banks:
GET /power_banks/search
admin only- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
, Params:{ "query": "search_term" }
- Response:
[ { "id": 1, "name": "Power Bank 1", "status": "available" }, ... ]
- Request: Headers:
-
Take Power Bank:
PUT /power_banks/:id/take
- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
- Response:
{ "id": 1, "name": "Power Bank 1", "status": "in_use" }
- Request: Headers:
-
Return Power Bank:
PUT /power_banks/:id/return
- Request: Headers:
{ "Authorization": "Bearer jwt_token" }
- Response:
{ "id": 1, "name": "Power Bank 1", "status": "available" }
- Request: Headers:
To run the test suite, use the following command:
bundle exec rspec
- Implement validations and error handling.
- Add pagination for Power Banks listing.
- Include search functionality.
- Deploy the project using your preferred platform.
- Implement a simple front-end using a framework of your choice.