Skip to content

Pyramid-Systems-Inc/OmniDesk

Repository files navigation

OmniDesk — Multi-Tenant Helpdesk SaaS (Portfolio Project)

OmniDesk is a production-style multi-tenant Helpdesk SaaS built to showcase real backend engineering: authentication, org-level RBAC, tenant isolation, integration testing with Testcontainers, and (next) tickets, audit logs, caching, rate limiting, and background jobs.

Tech Stack

Backend

  • ASP.NET Core (net9.0)
  • EF Core + PostgreSQL
  • ASP.NET Core Identity (GUID keys)
  • JWT Authentication
  • Multi-tenancy via OrganizationId + X-Org-Id request header
  • Policy-based Authorization (RBAC): Owner/Admin/Member/Viewer
  • Swagger (Swashbuckle) + Serilog
  • Integration Tests: xUnit + Testcontainers PostgreSQL + Respawn

Frontend (planned)

  • Next.js + React + TypeScript + Tailwind CSS

Repo Structure

/src
  /OmniDesk.Api
  /OmniDesk.Application
  /OmniDesk.Domain
  /OmniDesk.Infrastructure
/tests
  /OmniDesk.Api.IntegrationTests
/infra
  docker-compose.yml
/docs

Running Locally

1) Start infrastructure (Postgres + Redis)

Uses Docker Compose. Your local dev DB can be separate from the integration test DB.

docker compose -f infra/docker-compose.yml up -d
docker ps

2) Apply migrations to local dev database

dotnet ef database update --project src/OmniDesk.Infrastructure --startup-project src/OmniDesk.Api

3) Run API

dotnet run --project src/OmniDesk.Api

Open:

  • Swagger: http://localhost:<port>/swagger
  • Health: http://localhost:<port>/health

Integration Tests (Self-contained)

Integration tests run against a fresh PostgreSQL container automatically:

dotnet test

Authentication & Multi-Tenancy

Auth Endpoints

  • POST /auth/register
  • POST /auth/login
  • GET /auth/me

Orgs

  • GET /orgs (list orgs where current user is a member)
  • POST /orgs (create org and make creator Owner)

Org Members (Tenant-scoped)

  • GET /orgs/{orgId}/members (Admin+)
  • PATCH /orgs/{orgId}/members/{userId} (Owner only)

Tenant Header

Tenant context is resolved from:

  • X-Org-Id: <org-guid>

For tenant-scoped endpoints, clients should send:

  • Authorization: Bearer <token>
  • X-Org-Id: <orgId>

Notes / Known Behavior

  • Missing or mismatched X-Org-Id may currently yield 403 Forbidden (authorization fails before MVC filters run).
    • We can later adjust pipeline to return 400 BadRequest for tenant header errors.
  • FluentAssertions prints a license warning; we may replace it with built-in xUnit asserts or another assertion library later.

License

Portfolio project (no production license currently).

About

A production-style multi-tenant Helpdesk SaaS built to showcase real backend engineering

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages