A comprehensive Spring Boot REST API for managing academic notes with a hierarchical structure: Stream β Semester β Subject β Note. Features include JWT authentication, role-based access control, and Google Cloud Storage integration for PDF file management. Live_Link_click
- Login Image and user pages

- Admin pages add,delete sem-streams and subject also add files and delete files!

- Hierarchical Structure: Organize notes by Stream (CSE, ECE, etc.) β Semester (1-8) β Subject β Individual Notes
- JWT Authentication: Secure token-based authentication with role-based access control
- Role-Based Authorization:
ADMIN: Full CRUD operationsUSER: Read-only access
- Google Cloud Storage: Automated PDF file uploads with signed URLs
- RESTful API: 16 well-documented endpoints for complete CRUD operations
- MySQL Database: Persistent storage with JPA/Hibernate
- URL Encoding: Proper handling of file paths with spaces and special characters
Stream (e.g., CSE, ECE)
βββ Semester (1-8)
βββ Subject (e.g., Data Structures)
βββ Note (PDF files with titles)
Example GCS Path: notes-pdfs/CSE/3/Data Structures/lecture.pdf
- Framework: Spring Boot 3.3.4
- Language: Java 21
- Database: MySQL 8.0+
- Cloud Storage: Google Cloud Storage
- Security: Spring Security + JWT (HS256)
- Build Tool: Maven
- ORM: JPA/Hibernate
- Java 21+
- Maven 3.6+
- MySQL 8.0+
- Google Cloud Platform account with Cloud Storage enabled
- GCS Service Account JSON key file
git clone https://github.com/subramanya-44/unifeed.git
cd unifeedCreate a database:
CREATE DATABASE notes_db;Edit src/main/resources/application.properties:
# MySQL Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/notes_db
spring.datasource.username=your_mysql_username
spring.datasource.password=your_mysql_password
# JWT Configuration
jwt.secret=your-256-bit-secret-key-here-must-be-at-least-32-chars-long
jwt.expiration=1800000
# GCS Configuration
gcs.bucket.name=your-gcs-bucket-name
gcs.credentials.location=path/to/your-service-account-key.json- Create a GCS bucket (e.g.,
notes-pdfs) - Create a service account with Storage Object Admin role
- Download the JSON key file
- Place it in your project root (it's already in
.gitignore)
# Build the project
mvn clean install
# Run the application
mvn spring-boot:runThe application will start on http://localhost:8080
The system comes with two pre-configured users:
| Password | Role | |
|---|---|---|
| check_code | 1234 | ADMIN |
| user@example.com | 1234 | USER |
| Method | Endpoint | Description | Access |
|---|---|---|---|
| POST | /auth/login |
Login and get JWT token | Public |
| Method | Endpoint | Description | Access |
|---|---|---|---|
| GET | /streams |
Get all streams | USER, ADMIN |
| POST | /streams |
Create a stream | ADMIN |
| GET | /streams/{id} |
Get stream by ID | USER, ADMIN |
| DELETE | /streams/{id} |
Delete a stream | ADMIN |
| Method | Endpoint | Description | Access |
|---|---|---|---|
| GET | /streams/{streamId}/semesters |
Get semesters for a stream | USER, ADMIN |
| POST | /streams/{streamId}/semesters |
Create a semester | ADMIN |
| GET | /semesters/{id} |
Get semester by ID | USER, ADMIN |
| DELETE | /semesters/{id} |
Delete a semester | ADMIN |
| Method | Endpoint | Description | Access |
|---|---|---|---|
| GET | /semesters/{semesterId}/subjects |
Get subjects for a semester | USER, ADMIN |
| POST | /semesters/{semesterId}/subjects |
Create a subject | ADMIN |
| GET | /subjects/{id} |
Get subject by ID | USER, ADMIN |
| DELETE | /subjects/{id} |
Delete a subject | ADMIN |
| Method | Endpoint | Description | Access |
|---|---|---|---|
| GET | /subjects/{subjectId}/notes |
Get notes for a subject | USER, ADMIN |
| POST | /subjects/{subjectId}/notes |
Upload a note (multipart/form-data) | ADMIN |
| GET | /notes/{id} |
Get note by ID | USER, ADMIN |
| DELETE | /notes/{id} |
Delete a note | ADMIN |
curl -X POST http://localhost:8080/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "admin@example.com",
"password": "1234"
}'Response:
{
"accessToken": "eyJhbGciOiJIUzI1NiJ9...",
"expiresIn": 1800000,
"role": "ADMIN"
}curl -X POST http://localhost:8080/streams \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Computer Science Engineering"}'curl -X POST http://localhost:8080/streams/1/semesters \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"number": 3}'curl -X POST http://localhost:8080/semesters/1/subjects \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Data Structures and Algorithms"}'curl -X POST http://localhost:8080/subjects/1/notes \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "title=Lecture 1 - Introduction" \
-F "file=@/path/to/your/lecture.pdf"Response:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Lecture 1 - Introduction",
"fileUrl": "https://storage.googleapis.com/notes-pdfs/CSE%2F3%2FData%20Structures%2Flecture.pdf",
"subjectId": 1,
"subjectName": "Data Structures and Algorithms"
}curl http://localhost:8080/subjects/1/notes \
-H "Authorization: Bearer YOUR_TOKEN"π For more examples, see API-COMPLETE-GUIDE.md
src/main/java/com/app/notes/
βββ config/ # Security and JWT configuration
β βββ JwtFilter.java
β βββ JwtUtil.java
β βββ SecurityConfig.java
βββ controller/ # REST API endpoints
β βββ AuthController.java
β βββ NoteController.java
β βββ StreamController.java
β βββ SemesterController.java
β βββ SubjectController.java
βββ dto/ # Data Transfer Objects
β βββ AuthResponse.java
β βββ LoginRequest.java
β βββ NoteRequest.java
β βββ NoteResponse.java
βββ model/ # JPA Entities
β βββ Note.java
β βββ Stream.java
β βββ Semester.java
β βββ Subject.java
βββ repository/ # JPA Repositories
β βββ NoteRepository.java
β βββ StreamRepository.java
β βββ SemesterRepository.java
β βββ SubjectRepository.java
βββ service/ # Business Logic
β βββ AuthService.java
β βββ NoteService.java
β βββ StreamService.java
β βββ SemesterService.java
β βββ SubjectService.java
β βββ StorageService.java
βββ NotesApplication.java
- JWT Tokens: 30-minute expiration (configurable)
- Password Storage: Passwords are hardcoded in
AuthService(update for production!) - Role-Based Access: Spring Security with method-level authorization
- CORS: Configure for your frontend origin in production
- Sensitive Files: Excluded via
.gitignore
# Find process on port 8080
lsof -i :8080
# Kill the process
kill -9 <PID>Tokens expire after 30 minutes. Request a new token via /auth/login.
- Verify service account has Storage Object Admin role
- Check bucket name in
application.properties - Ensure JSON key file path is correct
- Verify MySQL is running
- Check database credentials in
application.properties - Ensure
notes_dbdatabase exists
- Update database credentials
- Replace hardcoded users with database authentication
- Configure CORS for frontend origin
- Use environment variables for sensitive data
- Enable HTTPS
- Update JWT secret key (use environment variable)
- Set up proper logging
- Configure GCS with production bucket
- Set up CI/CD pipeline
export DB_URL=jdbc:mysql://production-db:3306/notes_db
export DB_USERNAME=prod_user
export DB_PASSWORD=secure_password
export JWT_SECRET=your-production-secret-key-here
export GCS_BUCKET=production-notes-bucket
export GCS_CREDENTIALS=/path/to/prod-key.jsonThis project is open source and available under the MIT License.
Subramanya T N
- GitHub: @subramanya-44
- Repository: unifeed
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- User registration endpoint
- Email verification
- Password reset functionality
- File deletion from GCS when deleting notes
- Cascade delete for hierarchical entities
- Pagination for large result sets
- Search and filter endpoints
- File type validation (PDF only)
- File size limits
- Rate limiting
- API documentation with Swagger/OpenAPI
- Unit and integration tests
- Docker containerization
- Kubernetes deployment configs
If you encounter any issues or have questions:
- Check the API-COMPLETE-GUIDE.md
- Review the troubleshooting section above
- Open an issue on GitHub
β If you find this project helpful, please give it a star!