A Spring Boot REST API for a collaborative todo/task management application with user authentication and task assignment features.
- User Authentication: JWT-based authentication with registration and login
- Task Management: Create, read, update, and delete tasks
- Task Assignment: Assign tasks to users and manage ownership
- Self-Assignment: Users can assign themselves to unassigned tasks
- Task Completion: Track task completion status with completion updates
- Access Control: Users can only see:
- Unassigned tasks (assignedId = null)
- Tasks they own (ownerId = current user)
- Tasks assigned to them (assignedId = current user)
- Completion Control: Only task owners or assignees can update completion status
- Priority Management: Support for LOW, NORMAL, and HIGH priority tasks
- Due Date Tracking: Set and manage task due dates
- Database Integration: PostgreSQL database with JPA/Hibernate
- Java 21
- Spring Boot 3.4.9
- Spring Security (JWT Authentication)
- Spring Data JPA (Database Access)
- PostgreSQL 15 (Database)
- Docker & Docker Compose (Database Setup)
- Maven (Build Tool)
- Java 21 or higher
- Maven 3.6+
- Docker and Docker Compose
git clone <repository-url>
cd TodoTeam
docker compose up -d
This will start a PostgreSQL database with:
- Database: TodoTeamDB
- Username: postgres
- Password: postgres
- Port: 5432
mvn spring-boot:run
The application will start on http://localhost:8080
The application is configured to use PostgreSQL with the following default settings in application.yml
:
spring:
datasource:
url: jdbc:postgresql://localhost:5432/TodoTeamDB
username: postgres
password: postgres
To use different database credentials:
-
Update
application.yml
:spring: datasource: username: your_username password: your_password
-
Update
docker-compose.yml
:environment: POSTGRES_USER: your_username POSTGRES_PASSWORD: your_password
-
Restart the database:
docker compose down -v docker compose up -d
You can use environment variables for sensitive configuration:
spring:
datasource:
url: ${DATABASE_URL:jdbc:postgresql://localhost:5432/TodoTeamDB}
username: ${DB_USERNAME:postgres}
password: ${DB_PASSWORD:postgres}
Then set the environment variables:
export DATABASE_URL=jdbc:postgresql://your-host:5432/your-database
export DB_USERNAME=your_username
export DB_PASSWORD=your_secure_password
POST /auth/register
- Register a new userPOST /auth/login
- Login and get JWT token
GET /tasks
- Get accessible tasks for current userGET /tasks/{id}
- Get specific task (if accessible)POST /tasks
- Create a new taskPUT /tasks/{id}
- Update a task (owner only, except for completion and self-assignment)DELETE /tasks/{id}
- Delete a task (owner only)
GET /users/me
- Get current user information
GET /status
- Health check endpoint
The application implements strict access control for tasks:
- Unassigned Tasks: Visible to all users (assignedId = null)
- Owned Tasks: Users can see tasks they created (ownerId = current user)
- Assigned Tasks: Users can see tasks assigned to them (assignedId = current user)
Users cannot see tasks that don't meet any of these criteria.
The application has different permission levels for updating tasks:
- Task Owners: Can update all task properties (description, priority, dueDate, assigneeId, completed)
- Task Assignees: Can only update the completion status (
completed
field) - Self-Assignment: Any user can assign themselves to an unassigned task (assignedId = null)
- Completion Updates: Both owners and assignees can mark tasks as completed or incomplete
curl -X POST http://localhost:8080/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"username": "user",
"password": "password123"
}'
curl -X POST http://localhost:8080/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "password123"
}'
curl -X POST http://localhost:8080/tasks \
-H "Authorization: Bearer <your-jwt-token>" \
-H "Content-Type: application/json" \
-d '{
"title": "Complete project",
"description": "Finish the TodoTeam backend",
"priority": "HIGH",
"dueDate": 1693872000000,
"assigneeId": 2
}'
curl -H "Authorization: Bearer <your-jwt-token>" \
http://localhost:8080/tasks
curl -X PUT http://localhost:8080/tasks/1 \
-H "Authorization: Bearer <owner-jwt-token>" \
-H "Content-Type: application/json" \
-d '{
"description": "Updated description",
"priority": "HIGH",
"dueDate": 1693872000000,
"assigneeId": 2,
"completed": true
}'
curl -X PUT http://localhost:8080/tasks/1 \
-H "Authorization: Bearer <assignee-jwt-token>" \
-H "Content-Type: application/json" \
-d '{
"completed": true
}'
curl -X PUT http://localhost:8080/tasks/1 \
-H "Authorization: Bearer <your-jwt-token>" \
-H "Content-Type: application/json" \
-d '{
"assigneeId": <your-user-id>
}'
mvn test
mvn clean package
java -jar target/TodoTeam-0.0.1-SNAPSHOT.jar
The application uses Hibernate with create-drop
strategy for development, which recreates the database schema on each restart. For production, change this to update
or validate
in application.yml
:
spring:
jpa:
hibernate:
ddl-auto: update # or 'validate' for production
-
Ensure Docker is running and the PostgreSQL container is healthy:
docker compose ps
-
Check database logs:
docker compose logs postgres
-
Verify database credentials match between
application.yml
anddocker-compose.yml
- Check if port 8080 is available
- Verify Java 21 is installed:
java --version
- Ensure Maven dependencies are downloaded:
mvn clean compile
- Ensure JWT tokens are included in the
Authorization: Bearer <token>
header - Check token expiration (default: 12 hours)
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.