This project is part of the first semester project course at the University of Lleida (UdL). It serves as the backend for the UniHub application. This API includes the following main features:
- Configurable user profiles, matching their preferences with listings and communities
- Housing search (rooms/apartments) with filters
- Real-time chat (1:1 and groups)
- University communication channel
- Landlord–tenant/roommate group spaces
- Ratings & reviews (listings, landlords, tenants)
- Interest-based community channels
- [UniServices] Service listings (e.g., private tutoring)
- [UniItems] Second-hand marketplace (buy/sell items)
- [UniCommunities] Sponsored promotions in community chats (venues/events)
- [UniCar] Student carpooling with in-app payments and commissions
- Framework: FastAPI
- Database: PostgreSQL with SQLAlchemy
- Package Manager: uv
- Testing: pytest
- Code Quality: Ruff
- CI/CD: GitHub Actions
macOS/Linux:
curl -LsSf https://astral.sh/uv/install.sh | shWindows (PowerShell):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"Alternative (using pip):
pip install uvNote
After installation, restart your terminal or run source ~/.bashrc (Linux/macOS) or restart PowerShell (Windows).
git clone https://github.com/Computer-Engineering-UdL/UniHub-Back
cd UniHub-Back
uv sync --group devCreate a .env file:
API_VERSION=/api/v1
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_USER=unihub
POSTGRES_PASSWORD="test"
POSTGRES_DB=unihubuv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8080Visit:
- API:
http://localhost:8080 - Docs:
http://localhost:8080/docs
uv run pytest# Format code
uv run ruff format .
# Check for issues
uv run ruff check .# Production dependency
uv add package-name
# Development dependency
uv add --dev package-name# Generate migration after model changes
uv run alembic revision --autogenerate -m "description"
# Apply all pending migrations
uv run alembic upgrade head
# Rollback last migration
uv run alembic downgrade -1
# View migration history
uv run alembic historyNote
Migrations run automatically on app startup. Manual commands are only needed for development.
# Build image
docker build -t unihub-backend .
# Run container
docker run -p 8080:8080 unihub-backendapp/
├── api/v1/endpoints/ # API routes
├── core/ # Configuration
├── crud/ # Database operations
├── models/ # Data models
├── services/ # Business logic
└── main.py # Entry point
tests/ # Tests
erDiagram
channel {
UUID id PK
VARCHAR(2048) channel_logo "nullable"
VARCHAR(50) channel_type
DATETIME created_at
VARCHAR(120) description "nullable"
VARCHAR(60) name "indexed"
}
channel_bans {
UUID id PK
UUID banned_by FK "nullable"
UUID channel_id FK
UUID user_id FK
BOOLEAN active
DATETIME banned_at
DATETIME duration
VARCHAR(255) motive
}
channel_unbans {
UUID id PK
UUID channel_id FK
UUID unbanned_by FK "nullable"
UUID user_id FK
VARCHAR(255) motive
DATETIME unbanned_at
}
user {
UUID id PK
VARCHAR(500) avatar_url "nullable"
DATETIME created_at
VARCHAR(255) email UK "indexed"
VARCHAR(100) first_name
BOOLEAN is_active
BOOLEAN is_verified
VARCHAR(100) last_name
VARCHAR(255) password
VARCHAR(20) phone "nullable"
VARCHAR(50) provider
VARCHAR(50) role
VARCHAR(20) room_number "nullable"
VARCHAR(100) university "nullable"
VARCHAR(50) username UK "indexed"
}
channel_members {
UUID channel_id PK,FK
UUID user_id PK,FK
BOOLEAN is_banned
DATETIME joined_at
VARCHAR(20) role
}
housing_offer {
UUID id PK
UUID category_id FK
UUID user_id FK
VARCHAR(255) address
NUMERIC area
VARCHAR(100) city
NUMERIC deposit "nullable"
TEXT description
DATE end_date "nullable"
BOOLEAN furnished
VARCHAR(10) gender_preference "nullable"
BOOLEAN internet_included
INTEGER num_bathrooms "nullable"
INTEGER num_rooms "nullable"
DATE offer_valid_until
DATETIME posted_date
NUMERIC price
DATE start_date
VARCHAR(20) status
VARCHAR(255) title
BOOLEAN utilities_included
}
housing_category {
UUID id PK
VARCHAR(50) name UK
}
housing_photo {
UUID id PK
UUID offer_id FK
DATETIME uploaded_at
VARCHAR(255) url
}
interest_category {
CHAR(32) id PK
VARCHAR(120) name UK
}
interest {
CHAR(32) id PK
CHAR(32) category_id FK
VARCHAR(120) name UK
}
user_interest {
CHAR(32) id PK
CHAR(32) interest_id FK "indexed"
UUID user_id FK "indexed"
}
message {
UUID id PK
UUID channel_id FK
UUID parent_message_id FK "nullable"
UUID user_id FK
VARCHAR(500) content
DATETIME created_at
BOOLEAN is_edited
DATETIME updated_at "nullable"
}
channel ||--o{ channel_bans : channel_id
user ||--o{ channel_bans : user_id
user ||--o{ channel_bans : banned_by
channel ||--o{ channel_unbans : channel_id
user ||--o{ channel_unbans : user_id
user ||--o{ channel_unbans : unbanned_by
channel ||--o{ channel_members : channel_id
user ||--o{ channel_members : user_id
user ||--o{ housing_offer : user_id
housing_category ||--o{ housing_offer : category_id
housing_offer ||--o{ housing_photo : offer_id
interest_category ||--o{ interest : category_id
user ||--o{ user_interest : user_id
interest ||--o{ user_interest : interest_id
channel ||--o{ message : channel_id
user ||--o{ message : user_id
message ||--o{ message : parent_message_id
![]() |
![]() |
![]() |
![]() |
![]() |




