TaskFlow is a backend API for managing organizations, projects, and tasks in a multi-tenant environment. It is designed to model how real SaaS tools (e.g. Linear, Jira, Notion) handle authentication, authorization, and data isolation across teams.
The system focuses on correct access control, clean domain boundaries, and production-ready architecture rather than simple CRUD operations.
- A single backend serves multiple organizations
- Users can belong to multiple organizations
- A user’s permissions depend on their role per organization
Users have roles per organization, not globally:
- Owner
- Admin
- Member
Permissions are enforced at:
- Queryset level (what data a user can see)
- Object permission level (what actions a user can perform)
- JWT-based authentication
- Secure login & registration
- Protected endpoints
- Create organizations
- Automatic owner membership creation
- Organization-scoped access
- User ↔ Organization relationship
- Role stored per membership
- Single source of truth for permissions
- Projects belong to organizations
- Only owners/admins can create projects
- Members have read-only access
- Tasks belong to projects
- Tasks can be assigned to members
- Only assigned members or privileged roles can update tasks
- Organization members can invite users via email
- Token-based invite acceptance
- Invite expiration handling
- Important actions are logged
- Provides an audit trail per organization
This project follows a domain-driven app structure, where each app owns its responsibility:
accounts/ → authentication & user model
organizations/ → organizations, memberships, invites
projects/ → projects within organizations
tasks/ → task management & workflow
activity/ → audit logs
common/ → shared utilities (testing helpers, etc.)
Membership is the core authorization model
All access checks flow through:
User → Membership → Organization → Project → Task
This ensures strict isolation between organizations.
User
│
├── Membership (role)
│ │
│ └── Organization
│ │
│ └── Project
│ │
│ └── Task
Two layers of protection are used:
Ensures users can only see objects they belong to.
Example:
Task.objects.filter(
project__organization__memberships__user=request.user
)Ensures users can only modify objects they are allowed to act on.
Example:
- Only assigned users can update a task
- Only owners/admins can create projects
- Python
- Django
- Django REST Framework
- PostgreSQL
- Docker & Docker Compose
- JWT Authentication
- Docker
- Docker Compose
docker-compose up --builddocker-compose exec web python manage.py migratedocker-compose exec web python manage.py createsuperuserAutomated tests cover:
- Authentication flow
- Organization membership logic
- Permission enforcement
- Task access control
Run tests with:
docker-compose exec web python manage.py testPOST /api/v1/auth/register/
POST /api/v1/auth/login/
POST /api/v1/organizations/
GET /api/v1/organizations/
POST /api/v1/projects/
GET /api/v1/projects/
POST /api/v1/tasks/
PATCH /api/v1/tasks/{id}/
POST /api/v1/invites/
POST /api/v1/invites/accept/{token}/
- Pagination & filtering
- Async email delivery for invites
- Webhooks / notifications
- Deployment (AWS / Fly.io / Railway)
- API documentation (Swagger / Redoc)