Loading repository data…
Loading repository data…
Nsanjayboruds / repository
RIVETO is a full-stack web application built with separate frontend and backend modules. The frontend manages the user interface using modern web technologies (HTML, CSS, JavaScript). The backend handles server-side logic, APIs, and data management. This project serves as a foundation for building scalable web applications with a clear separation
RIVETO is a modern, fullstack web application built for scalability, advanced analytics.
It features a robust admin panel for management, user tracking, advanced UI components, and secure file/image upload via Cloudinary.
git clone https://github.com/Nsanjayboruds/RIVETO.git
cd RIVETO
cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env
# In root
cd backend
npm install
cd ../frontend
npm install
Open two separate terminal windows to run the servers simultaneously:
Terminal 1 (Backend):
cd backend
npm run dev
Sample Endpoint (Express.js):
// /backend/routes/upload.js
const { CloudinaryStorage } = require("multer-storage-cloudinary");
const multer = require("multer");
const cloudinary = require("cloudinary").v2;
// Cloudinary config (use your .env)
cloudinary.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
const storage = new CloudinaryStorage({
cloudinary,
params: {
folder: "riveto_uploads",
allowed_formats: ["jpg", "png", "jpeg", "svg", "webp"],
},
});
const upload = multer({ storage });
router.post("/upload", upload.single("image"), (req, res) => {
res.json({ url: req.file.path });
});
/upload endpoint.Sample Usage:
const handleUpload = async (event) => {
const formData = new FormData();
formData.append("image", event.target.files[0]);
const response = await fetch("/api/upload", {
method: "POST",
body: formData,
});
const data = await response.json();
setImageUrl(data.url); // Save/display Cloudinary URL
};
Run lint checks:
npm run lint
RIVETO/
├── backend/
│ ├── controller/
│ ├── model/
│ ├── routes/
│ ├── middleware/
│ ├── services/
│ ├── .env.example
│ └── ...
├── frontend/
│ ├── src/
│ │ ├── components/
│ │ ├── pages/
│ │ ├── hooks/
│ │ ├── utils/
│ │ └── App.jsx
│ ├── public/
│ ├── .env.example
│ └── ...
├── README.md
└── ...
backend/.env.example)MONGODB_URI=
JWT_SECRET=
BASE_URL=http://localhost:5000
CLOUDINARY_CLOUD_NAME=
CLOUDINARY_API_KEY=
CLOUDINARY_API_SECRET=
frontend/.env.example)REACT_APP_API_URL=http://localhost:5000/api
REACT_APP_RAZORPAY_KEY=
We welcome bug reports, feature requests, and community feedback.
If you find a bug or security issue, please open an issue on GitHub with:
GitHub Issues: https://github.com/Nsanjayboruds/RIVETO/issues
Have an idea for improving RIVETO? Open a feature request issue and describe your suggestion.
Use GitHub Discussions for:
GitHub Discussions: https://github.com/Nsanjayboruds/RIVETO/discussions
Before contributing, please star the repository ⭐
git checkout -b feature/YourFeature)git commit -m 'Add feature')git push origin feature/YourFeature)Please review CONTRIBUTING.md for details.
Thank you to all contributors who have helped make RIVETO better! 🚀
Want to see your name here? Check out our Contributing Guide!
MIT License. See LICENSE for details.
Built with React, Tailwind, Node.js, Express, MongoDB, Razorpay, and Cloudinary
This project implements a secure JWT refresh token flow with rotation:
Login
Issues an access token (15 minutes expiry) and a refresh token (7 days expiry).
Refresh tokens are hashed and stored in MongoDB.
Refresh
POST /api/auth/refresh rotates the refresh token on each use.
Old tokens are invalidated, new ones are stored.
Logout
POST /api/auth/logout clears both cookies and deletes the refresh token from DB.
This ensures sessions cannot be reused after logout.
Google & Admin Login
Both flows now issue access + refresh tokens, aligned with the same rotation/invalidation logic.
httpOnly, secure, and sameSite aware.403 Forbidden.Run the Jest test suite to validate login, refresh, and logout flows:
npm test