An educational, production-style REST API inspired by Twitter/X. It implements core social features (users, tweets, likes, comments, follows) using modern Spring Boot, stateless JWT authentication, and MySQL persistence.
This project serves as a learning platform showcasing clean layering, DTO mapping, role-based + ownership security, and comprehensive OpenAPI documentation suitable for extension into a full social feed system.
Implemented:
- User registration & login (JWT bearer)
- Granting admin role
- User CRUD with admin/ownership rules
- Tweets: create, list (public), filter by author, retrieve, update, delete
- Likes: like/unlike tweets, list likes by tweet or user
- Comments: create, list by tweet, retrieve, update, delete
- Follow system: follow/unfollow users, list followers & following
- Centralized exception handling with structured error response
- Input validation on request DTOs
- OpenAPI configuration + Swagger UI redirect (
/docs)
Security Highlights:
- Stateless JWT filter
- Method-level authorization (
@PreAuthorize) for sensitive operations - Granular role + principal-based access (admin vs owner)
- Java 21
- Spring Boot 3.5 (Web, Validation, Security, Data JPA)
- Springdoc OpenAPI 3 (Swagger UI)
- JWT (Auth0
java-jwt) - MySQL (development persistence)
- Lombok (boilerplate reduction)
- Maven (build + dependency management)
Layered structure emphasizing separation of concerns:
controllerβ HTTP / input boundaryserviceβ business logic & security checks (ownership, role checks)repositoryβ persistence via Spring Data JPAentityβ JPA mapped domain modelsdto+mapperβ transport and transformation layersinfra/securityβ JWT parsing & authentication filterexceptionβ domain-specific and validation exception handling
src/main/java/dev/tuchanski/api
βββ config # OpenAPI, Web, Security configuration
βββ controller # REST controllers (auth, users, tweets, likes, comments, follows)
βββ dto # Request/response DTOs per feature
βββ entity # JPA entities (User, Tweet, Like, Comment, Follow)
βββ exception # Custom exception hierarchy & handler
βββ infra/security # JWT filter & helper classes
βββ mapper # Entity <-> DTO conversion logic
βββ repository # Spring Data JPA repositories
βββ service # Business logic & token services
Default settings in src/main/resources/application.properties:
- Server port:
8080 - MySQL URL:
jdbc:mysql://localhost:3307/twitter - MySQL credentials:
root/secret(change for real use) - Hibernate DDL:
spring.jpa.hibernate.ddl-auto=update(dev only) - JWT secret property:
api.security.token.secret
Override by editing the properties file or providing environment variables / JVM system properties at runtime.
Prerequisites:
- Java 21 installed
- Maven 3.9+ (or use wrapper)
- Local MySQL instance (adjust URL/credentials if different)
Windows (PowerShell):
./mvnw.cmd clean spring-boot:run
Unix/macOS:
./mvnw clean spring-boot:run
After startup the API is available at: http://localhost:8080
Swagger UI: http://localhost:8080/docs (redirects to /swagger-ui/index.html)
- Obtain a JWT via
POST /api/auth/login. - Send token on protected requests:
Authorization: Bearer <token>. - Public endpoints: login/register, listing & retrieving tweets, reading comments, reading users (GET), OpenAPI docs.
- Protected endpoints enforce roles or ownership via
@PreAuthorizeand service-layer checks. - Passwords stored using BCrypt.
Base path prefix: /api
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /auth/register |
Public | Register a new user |
| POST | /auth/login |
Public | Authenticate and receive JWT |
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /users |
Admin | Create user |
| GET | /users |
Admin | List all users |
| GET | /users/{id} |
Admin or Owner | Get user by UUID |
| GET | /users/username/{username} |
Admin or Owner | Get user by username |
| PATCH | /users/{id} |
Admin or Owner | Partial update |
| DELETE | /users/{id} |
Admin or Owner | Delete user |
| PATCH | /users/{id}/admin |
Admin | Grant admin role |
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /tweets |
Public | List all tweets (optional ?username= filter) |
| GET | /tweets/{id} |
Public | Get tweet by UUID |
| POST | /tweets |
Bearer | Create tweet |
| PUT | /tweets/{id} |
Bearer (Owner) | Update tweet content |
| DELETE | /tweets/{id} |
Bearer (Owner) | Delete tweet |
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /tweets/{tweetId}/likes |
Bearer | Like a tweet |
| GET | /likes/{likeId} |
Public | Get like by UUID |
| GET | /tweets/{tweetId}/likes |
Public | List likes for tweet |
| GET | /users/{username}/likes |
Public | List likes by user |
| DELETE | /tweets/{tweetId}/likes |
Bearer (Owner) | Remove like (current user) |
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /tweets/{tweetId}/comments |
Bearer | Create comment on tweet |
| GET | /comments/{id} |
Public | Retrieve comment by UUID |
| GET | /tweets/{tweetId}/comments |
Public | List comments of tweet (desc creation time) |
| PUT | /comments/{id} |
Bearer (Owner) | Update comment |
| DELETE | /comments/{id} |
Bearer (Owner) | Delete comment |
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /users/{usernameFollowTarget}/follow |
Bearer | Follow a user |
| GET | /users/{username}/following |
Public | List users followed by username |
| GET | /users/{username}/followers |
Public | List users following username |
| DELETE | /users/{usernameUnfollowTarget}/follow |
Bearer | Unfollow a user |
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /docs |
Public | Redirect to Swagger UI |
| GET | /swagger-ui/** |
Public | Swagger UI assets |
| GET | /v3/api-docs/** |
Public | Raw OpenAPI JSON |
Register:
curl -X POST http://localhost:8080/api/auth/register \
-H "Content-Type: application/json" \
-d '{"name":"Jane Doe","username":"janed","email":"jane@example.com","password":"pass1234"}'Login:
curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"janed","password":"pass1234"}'Create tweet:
curl -X POST http://localhost:8080/api/tweets \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <jwt>" \
-d '{"content":"Hello, world!"}'Like tweet:
curl -X POST http://localhost:8080/api/tweets/<tweet-uuid>/likes \
-H "Authorization: Bearer <jwt>"Comment on tweet:
curl -X POST http://localhost:8080/api/tweets/<tweet-uuid>/comments \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <jwt>" \
-d '{"content":"Nice post!"}'Follow user:
curl -X POST http://localhost:8080/api/users/otheruser/follow \
-H "Authorization: Bearer <jwt>"OpenAPI metadata is defined in OpenApiConfig. Access interactive docs at:
http://localhost:8080/docs
Raw spec (JSON):
http://localhost:8080/v3/api-docs
Use these endpoints for client generation or exploration.
Security scheme name: bearerAuth (standard HTTP Bearer JWT).
- User: id (UUID), name, username, email, password (BCrypt), bio, roles, timestamps
- Tweet: id (UUID), content, author (User), timestamps
- Like: id (UUID), user, tweet, timestamps
- Comment: id (UUID), user, tweet, content, timestamps
- Follow: id (UUID), follower (User), followed (User), timestamp
Contributions welcome! Feel free to open issues or PRs for improvements, refactors, or new features. Please keep code style consistent and ensure new endpoints are documented with OpenAPI annotations.
Licensed under the MIT License. This codebase is for educational purposes; do not deploy as-is to production without hardening (secrets management, proper CORS, rate limiting, logging, monitoring, and stricter security settings).