-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 744e215
Showing
34 changed files
with
5,290 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
AUTH_MAIL_USER=<> | ||
AUTH_MAIL_PASSWORD=<> | ||
|
||
MERCADO_PAGO_ACCESS_TOKEN_TEST=<> | ||
MERCADO_PAGO_ACCESS_TOKEN_PROD=<> | ||
|
||
HOST=<> | ||
PORT=<> | ||
DATABASE=<> | ||
USERNAME=<> | ||
PASSWORD=<> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
node_modules | ||
.idea | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2023 JFECM | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# Backend-Gym | ||
|
||
This is a project that uses the Express.js framework and MongoDB to create a REST-Ful API. It allows managing operations of a gym. | ||
|
||
## General Description | ||
|
||
The application manages resources and provides basic CRUD (Create, Read, Update, Delete) operations for users, equipment and plans. | ||
|
||
## Project Structure | ||
|
||
The project is organized as follows: | ||
- `index.js`: Application entry point. | ||
- `package.json`: Dependency management files. | ||
- `controllers/`: All controllers | ||
- `middleware/`: Custom middleware. | ||
- `models/`: Data model definitions. | ||
- `routes/`: Application routes definitions. | ||
- `.env`: Env file `(you need create this file)` | ||
- `.env.sample`: Configuration file sample with environment variables for .env file. | ||
|
||
## Requirements | ||
|
||
- Make sure you have Node installed and the dependencies defined in the `package.json` file. | ||
- Make sure you have MongoDB installed and check MongoDB connection configuration. | ||
|
||
## Use (local) | ||
|
||
1. Clone this repository or download the source code. | ||
2. Make sure all dependencies are installed. | ||
3. Start the application using `npm run dev`. | ||
4. The API will be available at `http://localhost:3000`. | ||
|
||
## API Routes | ||
### Authentication | ||
|
||
- `POST /api/v2/auth/sign-in`: Sign in | ||
- `POST /api/v2/auth/sign-up`: Sign up | ||
|
||
### Admin | ||
|
||
- `POST /api/v2/admin/create-admin`: Create Admin. | ||
- `POST /api/v2/admin/create-coach`: Create Coach. | ||
- `POST /api/v2/admin/create-member/plan/:id`: Create Member. | ||
- `GET /api/v2/admin/users`: Get All Users. | ||
- `POST /api/v2/admin/create-admin`: Create Admin. | ||
- `POST /api/v2/admin/create-coach`: Create Coach. | ||
- `POST /api/v2/admin/create-member/plan/:id`: Create Member. | ||
- `GET /api/v2/admin/users`: Get All Users. | ||
- `GET /api/v2/admin/users/:id`: Get User by ID. | ||
- `POST /api/v2/admin/create-payment`: Create Payment. | ||
- `POST /api/v2/admin/create-equipment`: Create Equipment. | ||
- `POST /api/v2/admin/create-plan`: Create Plan. | ||
- `GET /api/v2/admin/plans`: Get All Plans. | ||
- `GET /api/v2/admin/sales-report`: Get Sales Report. | ||
- `GET /api/v2/admin/users/:id/generate-access-credentials`: Generate Access Credentials for a User. | ||
- `DELETE /api/v2/admin/users/:id`: Delete User by ID. | ||
- `PUT /api/v2/admin/users/:id`: Update User by ID. | ||
- `PUT /api/v2/admin/users/:id/change-password`: Update User Password by ID. | ||
- `PUT /api/v2/admin/memberships`: Associate User with Plan. | ||
|
||
## Contribution | ||
|
||
If you would like to contribute to this project, feel free to do so. | ||
|
||
You can open an issue, submit a pull request, or work on improvements or new features. | ||
|
||
All contributions are welcome! | ||
|
||
## License | ||
|
||
This project is licensed under the MIT License. You can find more details in the [LICENSE](LICENSE) file. | ||
|
||
## Contact | ||
|
||
If you have any questions or comments, feel free to contact me via my email address or the GitHub repository. | ||
|
||
Thank you for your interest in this project! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
const jwt = require('jsonwebtoken'); | ||
const authCtrl = {}; | ||
const User = require("../models/user"); | ||
const bcrypt = require("bcrypt"); | ||
|
||
authCtrl.verifyToken = async (req, res, next) => { | ||
if (!req.headers.authorization) { | ||
return res.status(401).json({ | ||
success: false, | ||
message: "Authorization header is missing.", | ||
}); | ||
} | ||
|
||
const split = req.headers.authorization.split(' '); | ||
let token; | ||
|
||
if (split.length >= 2) { | ||
token = split[1]; | ||
} else { | ||
return res.status(401).json({ | ||
success: false, | ||
message: "Invalid authorization format.", | ||
}); | ||
} | ||
|
||
if (!token) { | ||
return res.status(401).json({ | ||
success: false, | ||
message: "Token is missing in authorization header.", | ||
}); | ||
} | ||
|
||
try { | ||
const payload = jwt.verify(token, "secretkey"); | ||
req.userId = payload._id; | ||
req.userRol = payload.rol; | ||
req.user = payload; | ||
next(); | ||
} catch (error) { | ||
return res.status(401).json({ | ||
success: false, | ||
message: "Invalid or expired token.", | ||
}); | ||
} | ||
}; | ||
|
||
authCtrl.signIn = async (req, res) => { | ||
const {username, password} = req.body; | ||
|
||
try { | ||
const user = await User.findOne({username}); | ||
|
||
if (!user) { | ||
return res.status(401).json({ | ||
success: false, | ||
message: "Authentication failed. User not found.", | ||
}); | ||
} | ||
|
||
const isPasswordValid = await bcrypt.compare(password, user.password); | ||
|
||
if (!isPasswordValid) { | ||
return res.status(401).json({ | ||
success: false, | ||
message: "Authentication failed. Incorrect password.", | ||
}); | ||
} | ||
|
||
const token = jwt.sign({id: user._id, rol: user.rol}, "secretkey"); | ||
|
||
res.json({ | ||
success: true, | ||
message: "Authentication successful.", | ||
user: user, token: token | ||
}); | ||
|
||
} catch (error) { | ||
res.status(500).json({ | ||
success: false, | ||
message: "Internal server error.", | ||
error: error.message, | ||
}); | ||
} | ||
|
||
} | ||
|
||
authCtrl.signUp = async (req, res) => { | ||
const {username, password, rol} = req.body; | ||
|
||
try { | ||
const existingUser = await User.findOne({username}); | ||
|
||
if (existingUser) { | ||
return res.status(400).json({ | ||
success: false, | ||
message: "Username already exists. Please choose a different username.", | ||
}); | ||
} | ||
|
||
const hashedPassword = await bcrypt.hash(password, 10); | ||
|
||
const user = new User({ | ||
username, | ||
password: hashedPassword, | ||
rol: rol || 'user', | ||
}); | ||
|
||
await user.save(); | ||
|
||
res.json({ | ||
success: true, | ||
message: "User registered successfully.", | ||
user: user, | ||
}); | ||
|
||
} catch (error) { | ||
res.status(500).json({ | ||
success: false, | ||
message: "Internal server error.", | ||
error: error.message, | ||
}); | ||
} | ||
} | ||
|
||
module.exports = authCtrl; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
const equipmentCtrl = {}; | ||
const Equipment = require('../models/equipment'); | ||
const Plan = require("../models/plan"); | ||
|
||
equipmentCtrl.create = async (req, res) => { | ||
try { | ||
const {name, total, image} = req.body; | ||
|
||
const existingNameEquipment = await Equipment.findOne({ name }); | ||
if (existingNameEquipment) { | ||
return res.status(400).json({ | ||
success: false, | ||
message: "Name equipment already exists. Please choose a different name.", | ||
}); | ||
} | ||
|
||
const newEquipment = new Equipment({ | ||
name, | ||
total, | ||
status: 'active', | ||
image, | ||
}); | ||
|
||
await newEquipment.save(); | ||
|
||
res.json({ | ||
success: true, | ||
message: 'Equipment created successfully.', | ||
equipment: newEquipment, | ||
}); | ||
} catch (error) { | ||
res.status(500).json({ | ||
success: false, message: 'Internal server error.', error: error.message, | ||
}); | ||
} | ||
}; | ||
|
||
equipmentCtrl.get = async (req, res) => { | ||
try { | ||
const { id } = req.params; | ||
const equipment = await Equipment.findById(id); | ||
|
||
if (!equipment) { | ||
return res.status(404).json({ | ||
success: false, | ||
message: 'Equipment not found.', | ||
}); | ||
} | ||
|
||
res.json({ | ||
success: true, | ||
equipment: equipment, | ||
}); | ||
} catch (error) { | ||
res.status(500).json({ | ||
success: false, | ||
message: 'Internal server error.', | ||
error: error.message, | ||
}); | ||
} | ||
}; | ||
|
||
equipmentCtrl.getAll = async (req, res) => { | ||
try { | ||
const equipmentList = await Equipment.find(); | ||
|
||
res.json({ | ||
success: true, | ||
equipment: equipmentList, | ||
}); | ||
} catch (error) { | ||
res.status(500).json({ | ||
success: false, | ||
message: 'Internal server error.', | ||
error: error.message, | ||
}); | ||
} | ||
}; | ||
|
||
equipmentCtrl.update = async (req, res) => { | ||
try { | ||
const { id } = req.params; | ||
const { name, total, image } = req.body; | ||
|
||
const existingNameEquipment = await Equipment.findOne({ name }); | ||
if (existingNameEquipment) { | ||
return res.status(400).json({ | ||
success: false, | ||
message: "Name equipment already exists. Please choose a different name.", | ||
}); | ||
} | ||
|
||
const updatedEquipment = await Equipment.findByIdAndUpdate( | ||
id, | ||
{ name, total, image }, | ||
{ new: true } | ||
); | ||
|
||
if (!updatedEquipment) { | ||
return res.status(404).json({ | ||
success: false, | ||
message: 'Equipment not found.', | ||
}); | ||
} | ||
|
||
res.json({ | ||
success: true, | ||
message: 'Equipment updated successfully.', | ||
equipment: updatedEquipment, | ||
}); | ||
} catch (error) { | ||
res.status(500).json({ | ||
success: false, | ||
message: 'Internal server error.', | ||
error: error.message, | ||
}); | ||
} | ||
}; | ||
|
||
equipmentCtrl.delete = async (req, res) => { | ||
try { | ||
const { id } = req.params; | ||
const deletedEquipment = await Equipment.findByIdAndDelete(id); | ||
|
||
if (!deletedEquipment) { | ||
return res.status(404).json({ | ||
success: false, | ||
message: 'Equipment not found.', | ||
}); | ||
} | ||
|
||
res.json({ | ||
success: true, | ||
message: 'Equipment deleted successfully.', | ||
equipment: deletedEquipment, | ||
}); | ||
} catch (error) { | ||
res.status(500).json({ | ||
success: false, | ||
message: 'Internal server error.', | ||
error: error.message, | ||
}); | ||
} | ||
}; | ||
|
||
module.exports = equipmentCtrl; |
Oops, something went wrong.